PDA

View Full Version : Bank System


Twinny
09-22-2006, 05:52 AM
Bank system I made using dbnpc.

DBNPC Script (Name is BankDB):

function onCreated()
{
this.interest = 0.01;
this.hour = 0;
Interest();
setTimer(3600);
}
public function CreateAccount(pl,ammount)
{
if (this.accounts.index(pl) = -1)
{
this.accounts.add(pl);
this.("acc"@pl) = ammount;
findplayer(pl).rupees -= ammount;
return true
}
else return false;
}

public function CheckBalance(pl)
{
if (this.accounts.index(pl) => 0)
{
return this.("acc"@pl);
}
else return false;
}

public function AddMoney(pl,ammount)
{
if (this.accounts.index(pl) => 0)
{
findplayer(pl).rupees -= ammount;
this.("acc"@pl) += ammount;
return this.("acc"@pl);
}
else return false;
}

public function RemoveMoney(pl,ammount)
{
if (this.accounts.index(pl) => 0)
{
if (this.("acc"@pl) => ammount)
{
this.("acc"@pl) -= ammount;
findplayer(pl).rupees += ammount;
return true;
}
else return "nm";
}
else return "na";
}

function onTimeout()
{
/* Cheers to Kuji for this.hour idea */
this.hour ++;
if (this.hour => 24)
{
echo("Interest Added");
Interest();
this.hour = 0;
}
setTimer(3600);
}

public function Interest()
{
for (int : this.accounts)
{
this.("acc"@int) = int(this.("acc"@int) * 1.01);
}
}


Manual interest for RC - add this to your Control-NPC

function onRCChat()
{
if (params[0] == "interest")
{
if (player.account == "Whoever")
{
echo("Manual Interest Added!");
BankDB.Interest();
}
}
}


And finally some examples on how to use this system in a bank

/* Do not clientside this script */
function onPlayerChats()
{
/*Create Account*/
if (player.chat.starts("/createaccount"))
{
temp.result = BankDB.CreateAccount(player.account,player.chat.su bstring(15,-1));
if (temp.result == true)
say2("Account Opened");

else say2("You already have an account");
}

else if (player.chat == "/balance")
{
temp.result = BankDB.CheckBalance(player.account);
if(temp.result != false)
say2("Current Balance" SPC temp.result);
else say2("You do not have an account");
}

else if (player.chat.starts("/withdraw"))
{
temp.result = BankDB.RemoveMoney(player.account,player.chat.subs tring(10,-1));
if (temp.result == "na")
say2("Open an account?");
else if (temp.result == "nm")
say2("Not enough money");
else if (temp.result == true)
say2("Withdrawn");
}
else if (player.chat.starts("/deposit"))
{
if (player.rupees > player.chat.substring(9,-1))
{
temp.result = BankDB.AddMoney(player.account,player.chat.substri ng(9,-1));
if (temp.result != false)
say2("Money Deposited. Balance: " @ temp.result);
else
say2("Open an account first");
}
}
}

This system can work on a global scale. One BankDB can serve any ammount of banks. I used a BankDB for a couple of reasons. First off - incredibly easy to add interest now. Secondly - I can use functions to determine who has the most money, total ammount of money etc. (Not included).

Skyld
09-22-2006, 10:04 AM
Slightly different approach to how I would do it, but good none the less.

KuJi
09-22-2006, 02:12 PM
public function CreateAccount(pl,ammount)


Take a look at the bolded twinny ;)

Twinny
09-23-2006, 02:21 AM
So I can't spell for peanuts. Does this really matter? No? Good :) .

xAndrewx
09-23-2006, 10:18 AM
Slightly different approach to how I would do it, but good none the less.

I agree :S
Good though :)

Twinny
09-23-2006, 11:25 AM
Ok: How would you two do it?

xAndrewx
09-23-2006, 11:30 AM
Personally, I'd merge the Create account and Deposit into one. If the string inside the database doesn't exist, I'd then instantly create the bank account. I wouldn't use so many public functions, remember that they're public. I'd also convert your playerchats.

KuJi
09-23-2006, 12:07 PM
Clientside -> Trigger to Server -> Use ChatBar -> Ftw =O?

Skyld
09-23-2006, 12:32 PM
Ok: How would you two do it?
Well, the way that my system works is that I have a collection of public functions in a class which is joined to the player.
public function bankCreate();
public function bankDeposit();
public function bankWithdraw();
I also have other functions for checking if they have an account, checking the balance, etc.

I also have a DB NPC for storing the bank data, i.e.
DB_Bank.("bank_" @ this.account) = ...;
However, but it doesn't do any functioning itself.

Then, instead of having to pass the account name, I can just use the this. object to access the player so that you can just do this to deposit 30g:
player.bankDeposit(30);
It makes it:

Easier to type, and remember.
Easier for other people to pick up and use.
So that you don't have to pass the account name.

KuJi
09-23-2006, 12:49 PM
Hmm.. my atms a bit diff =o.

acc_123456=KuJi,PASSWORD,BALANCE

I should probally MD5 the password, maybe I will redo the ATM sometime soon.. is kinda old.

Anyway, when you use your ATM Card it has the ATM # in it automatically... so yeah.

Twinny
09-23-2006, 03:32 PM
I'd also convert your playerchats.

The playerchat stuff was just an example to show how to do it. Hopefully people will use something better eg a GUI.

That's a pretty good idea Skyld. May edit the code with a more user friendly version later ^^. I'm still pretty sucky at scripting but anything that seems half decent to me i'll share in the hope of receiving advice :)

xAndrewx
09-23-2006, 04:57 PM
Skyld's idea is good :]

k0rupt_ed
09-23-2006, 09:30 PM
you people inspire me.

Twinny
09-23-2006, 10:46 PM
To do what? ^^

Twinny
09-28-2006, 10:04 AM
Update!
Bank System v 1.1
After receving advice from Skyld I have made a improved bank system using classes.

DBNPC named BankDB

function onCreated()
{
this.interest = 0.01;
this.hour = 0;
Interest();
setTimer(3600);
}

function onTimeout()
{
this.hour ++;
if (this.hour => 24)
{
echo("Interest Added");
Interest();
this.hour = 0;
}
setTimer(3600);
}

public function Interest()
{
for (int : this.accounts)
{
this.("acc"@int) = int(this.("acc"@int) * 1.01);
}
}


Class with bank functions

public function bankCreate(amount)
{
if (BankDB.accounts.index(player.account) = -1)
{
if (player.rupees => amount)
{
BankDB.accounts.add(player.account);
BankDB.("acc"@player.account) = amount;
player.rupees -= amount;
return True;
}
else return "nem";
}
else return false;
}

public function bankDeposit(amount)
{
if (BankDB.accounts.index(player.account) => 0)
{
if (player.rupees => amount)
{
BankDB.("acc"@player.account) += amount;
player.rupees -= amount;
return true;
}
else return "nem"; //Not enough money
}
else return "nba"; //No bank account
}

public function bankWithdraw(amount)
{
if (BankDB.accounts.index(player.account) => 0)
{
if (BankDB.("acc"@player.account) => amount)
{
BankDB.("acc"@player.account) -= amount;
player.rupees += amount;
return true;
}
else return "nem";
}
else return "nba";
}

public function bankBalance()
{
if (BankDB.accounts.index(player.account) => 0)
{
return BankDB.("acc"@player.account);
}
else return "nba";
}

public function bankTransfer(amount,pl)
{
/* Lot's of Tests */
if (BankDB.accounts.index(player.account) => 0)
{
if(BankDB.accounts.index(pl) => 0)
{
if (BankDB.("acc"@player.account) => amount)
{
BankDB.("acc"@pl) += amount;
BankDB.("acc"@player.account) -= amount;
return true;
}
else return "nem";
}
else return "pdne"; //Player does not exist
}
else return "nba";
}


Finally add in your Control-NPC

function onActionPlayeronline()
{
player.join("classname");
}

function onRCChat()
{
if (params[0] == "interest")
{
if (player.account == "Whoever")
{
echo("Manual Interest Added!");
BankDB.Interest();
}
}
}


Commands Available

player.bankCreate(amount);
player.bankDeposit(amount);
player.bankWithdraw(amount);
player.bankBalance();
player.bankTransfer(amount,account);


Simple enough to use. Call the commands serverside eg. player.bankDeposit(400);

May add a GUI script to use the Bank system next.

xAndrewx
09-28-2006, 07:26 PM
You're using return quite alot, but you're not really giving reason why? Explain why you've used
'return "w/e";'
as some people may not get it.

Twinny
09-29-2006, 12:46 AM
Return tells whatever script accessed the commands the results of those commands. Eg. A NPC tries to withdraw 501 when you only have 500. It will receive "nem" and display the error message appropriately.

This in turn allows for customisation. Eg. a human banker may be polite about this while a rock troll banker will proceed to club you to death for not having enough money.

KuJi
09-29-2006, 03:39 AM
Return tells whatever script accessed the commands the results of those commands. Eg. A NPC tries to withdraw 501 when you only have 500. It will receive "nem" and display the error message appropriately.

This in turn allows for customisation. Eg. a human banker may be polite about this while a rock troll banker will proceed to club you to death for not having enough money.

I am pretty sure snk knows... (if that was directed to me).. he tells me to use it more =(

xAndrewx
09-29-2006, 09:31 AM
I know how it works, but you didn't seem to use any return error feature in your script. That's why I asked you about it :)

Twinny
09-29-2006, 12:10 PM
Well - the error feature basically is the 'nem' for instance. The script checks the return. If it is 'nem' then it displays it's own custom error message. What error feature would you be expecting? =o

[Edit]: For those who don't know to use RC commands simply type /npc <command> into RC. eg. /npc interest. If your account matches the test i've added then it will do the command.

xAndrewx
09-29-2006, 07:32 PM
Well - the error feature basically is the 'nem' for instance. The script checks the return. If it is 'nem' then it displays it's own custom error message. What error feature would you be expecting? =o

You don't use this feature in your script, this is what I am saying...

JkWhoSaysNi
09-29-2006, 08:08 PM
I use return on almost every function. I'm used to programming in OO languages and I learned OO in Eiffel where "deign by contract" is a major philosopy. Basically means making sure the function can go ahead with the data it's been given (preconditions) and then making sure it's completed successfully (postconditions) the only real way to implement this in GS is return codes on functions. (Check my associative array class for example)

In GS it's best to use numbers imho for the following reasons:

1) You can use if (function()) {} for functions that return 1 or 0.
2) You can use if (function() > 3) {} and make error checks in a sensible order. E.g. in this case the first 3 errors are acceptable.
3) Comparing strings is more CPU intensive than comparing integers.

xAndrewx
09-29-2006, 11:04 PM
I use return on almost every function. I'm used to programming in OO languages and I learned OO in Eiffel where "deign by contract" is a major philosopy. Basically means making sure the function can go ahead with the data it's been given (preconditions) and then making sure it's completed successfully (postconditions) the only real way to implement this in GS is return codes on functions. (Check my associative array class for example)

In GS it's best to use numbers imho for the following reasons:

1) You can use if (function()) {} for functions that return 1 or 0.
2) You can use if (function() > 3) {} and make error checks in a sensible order. E.g. in this case the first 3 errors are acceptable.
3) Comparing strings is more CPU intensive than comparing integers.
Everyone to their own. I prefer Skyld's methods!

Twinny
09-30-2006, 07:54 AM
If i post a gui bank client - it will make use of the new returns.

xAndrewx
09-30-2006, 09:24 AM
That's an If :p
I'm only questioning it, because you've used it yet not explained how it works. Other than that, cool :)

Crono
09-30-2006, 04:29 PM
man i rock you all at scripting

nice bank system, + rep

Twinny
10-01-2006, 05:09 AM
Woo thanks Gerami <3. Good to be acknowledged by the master >_<