Saturday, January 2, 2010

Show and Update Stats

Player stats are now checked and synchronized when they are pulled.

<?php
$pullStats = mysql_query('select * from player WHERE id = "'.$userid.'"');

while($row = mysql_fetch_assoc($pullStats)){
$gold = $row['gold'];
$username = $row['username'];
$health = $row['curhealth'];
$mind = $row['mind'];
$body = $row['body'];
$soul = $row['soul'];
$exp = $row['exp'];
$total = ($mind + $body + $soul);
$level = ($total) / 10;
$level = round($level);

$totalHealth = ($body + $soul) * 5;
$defense = ($total)/3 - 2;
$defense = round($defense);
$attack = ($total)/3;
$attack = round($attack);
$agility = ($body + $mind)/2;
$agility = round($agility);

$oldAgility = $row['agility'];
if ($oldAgility != $agility){

$updatePlayer = "UPDATE `shinigami`.`player` SET `agility` = '".$agility."'
WHERE `player`.`id` = '".$userid."' LIMIT 1;";
mysql_query($updatePlayer) or die(mysql_error());
}

$oldAttack = $row['attack'];
if ($oldAttack != $attack){

$updatePlayer = "UPDATE `shinigami`.`player` SET `attack` = '".$attack."'
WHERE `player`.`id` = 1 LIMIT 1;";
mysql_query($updatePlayer) or die(mysql_error());
}

$oldDefense = $row['defense'];
if ($oldDefense != $defense){

$updatePlayer = "UPDATE `shinigami`.`player` SET `defense` = '".$defense."'
WHERE `player`.`id` = 1 LIMIT 1;";
mysql_query($updatePlayer) or die(mysql_error());
}

$oldHealth = $row['health'];
if ($oldHealth != $totalHealth){

$updatePlayer = "UPDATE `shinigami`.`player` SET `health` = '".$totalHealth."'
WHERE `player`.`id` = 1 LIMIT 1;";
mysql_query($updatePlayer) or die(mysql_error());
}


}
?>

Player Log In/Out


Table "player" is for logging in and out a user (basic at the moment) and tracking stats. There is no registration system yet, but predefined characters can start playing what has been created.

There are 10 stats tracked by the database for each player.

Release v0.01a

First release, so don't expect much...

Saturday, January 2, 2010

Build 0.01a

[New Features]
+Auto-generate a hero starting stats
+Display the stats along with icons
+Auto-generate a random monster for the hero to fight
+Make sure enemy is in hero level and stat capability
+Display enemy information and picture
+Conduct a battle using an advanced randomized/stat based formulae.
+Display the results of the battle.
+Process win or loss scenario and punishments/rewards
+Randomize certain text to liven up repititive battle text.

[Files]
PHP 2 - 9 KB
IMG 16 - 44.8 KB

[Added]
index.php
raRe.php
changeLog.txt
img/
agility.gif
attack.gif
blocked.gif
body.gif
Bug.gif
health.gif
health.jpg
healthBig.gif
mind.gif
nmeHealth.gif
nmeHealth.jpg
skeleton.gif
slime.gif
soul.gif
versus.gif

Download 44 KB .rar

Battle output...



Battle Output.

The entire system is modular and the fight between two complete set of stats will always produce a valid result that reflects both general luck and skill. A randomizer is used to try and liven up some of the textual results as well. It can eventually be more fine-tuned to react to specific contexts.

The values, like monsters, players, and responses should be pulled from a database and adjusted accordingly.

//This is the randomized response engine
function response($response){
if ($response == "ATTACK"){
$attack[0] = "attack";
$attack[2] = "slash";
$attack[3] = "jab";
$attack[4] = "chop";
$attack[5] = "slash";
$attack[6] = "kick";
$attack[7] = "hurt";
$attack[8] = "pulverize";
$attack[9] = "cut";
$attack[1] = "upper-cut";
$responseBack = array_rand(array_flip($attack), 1);
echo $responseBack;
}

if ($response == "BLOCKED"){
$blocked[0] = "blocked";
$blocked[2] = "stopped";
$blocked[3] = "deflected";
$blocked[4] = "useless";
$blocked[5] = "too late";
$blocked[6] = "too early";
$blocked[7] = "absorbed";
$blocked[8] = "rejected";
$blocked[9] = "nullified";
$blocked[1] = "laughable";
$responseBack = array_rand(array_flip($blocked), 1);
echo $responseBack;
}
}

Battle to the Death!

This script automates a battle using the player and enemy stats generated. There is a chance for random blocks, evasions and random variation based upon the actual stats.

Some things to add in the next version is a check for special stats associated with a character's items or skills (burned, frozen, poisoned, scared, etc.) and apply the appropriate stat bonus or handicap during calculations.

Loot drops more in depth than what are currently in place could also be considered, with a treasure generation system based upon stats.

//Initiate Confrontation
echo "<br><br><b>Battle Phase</b><br><br> ";

//Who goes first?
$firstStrike = rand($level, $agility);
$nmeFirstStrike = rand($nmeLevel, $nmeAgility);
if($firstStrike >= $nmeFirstStrike){ $playerTurn = "Y"; } else { $playerTurn = "N"; }

//While player turn
while($playerTurn != "O"){

while($playerTurn == "Y"){
echo '<br><table border="1" bgcolor="#EEE666" text-align="left" width="50%"><tr><td style="padding: 10px;">';
//Attack Phase
//Is it dodged?
$struck = rand($level, $agility) + $agility;
$dodged = rand($nmeLevel, $nmeAgility) + $nmeLevel;

//Yes
if($dodged > $struck * 1.2){
//Output
echo "<font color=gray>Your attack was dodged!</font><br>";
$playerTurn = "N";

}
//No
else {
//Is it blocked?
$damaged = rand($level, $attack);
$blocked = rand($nmeLevel, $nmeDefense);
$totalDamage = $damaged - ($blocked * 0.6);
$totalDamage = round($totalDamage);
//Yes
if ($totalDamage <= 0){
$response = "BLOCKED";
//Output blocked
echo '<img src="img/blocked.gif" align="left"><font color=red>Your attack was <b>';
response($response);
echo "!</b></font><br>";
$playerTurn = "N";

}
//No
else {
//Calculate damage
$response = "VERB";
//Output damage
echo '<img src="img/attack.gif" align="left"><font color=blue>You <b>';
response($response);
echo "</b> the enemy for <b>".$totalDamage."</b> damage!</font><br>";

//Nme Health decreases
$nmeHealth = $nmeHealth - $totalDamage;
$nmeHelath = round($nmeHealth);

//Nme Defeated?
//Yes
if($nmeHealth <= 0){
//Output
echo "<br><i>NME Defeated!</i>";
$playerOutcome = "W";
$playerTurn = "O";
}
//No
else {
//Output enemy health remaining
echo 'The enemy now has <img src="img/nmeHealth.gif"><b>'.$nmeHealth.'</b> health.<br>';
$playerTurn = "N";
}
}

}


echo '</td></tr></table>';
}

//While enemy turn
while($playerTurn == "N"){
echo '<br><table border="1" bgcolor="#E6E6E6" text-align="left" width="50%"><tr><td style="padding: 10px;">';
//Attack Phase
//Is it dodged?
$struck = rand($nmeLevel, $nmeAgility) + $nmeAgility;
$dodged = rand($level, $agility) + $level;
//Yes
if($dodged >= $struck * 1.2){
//Output dodged
echo "<font color=gray>Enemy attack was <b>dodged!</b></font><br>";
$playerTurn = "Y";

}
//No
else {
$damaged = rand($nmeLevel, $nmeAttack);
$blocked = rand($level, $defense);
$totalDamage = $damaged - ($blocked * 0.6);
$totalDamage = round($totalDamage);

//Was it blocked?
//Yes
if ($totalDamage <= 0){
//Output blocked
$response = "BLOCKED";
echo '<img src="img/blocked.gif" align="left"><font color=blue>The Enemy attack was <b>';
response($response);
echo "!</b></font><br>";
$playerTurn = "Y";

}
//No
else {
//Calculate damage
$response = "VERB";
//Output damage
echo '<img src="img/attack.gif" align="left"><font color=red>The enemy <b>';
response($response);
echo "s</b> you for <b>".$totalDamage."</b> damage.</font><br>";

//Health decreases
$health = $health - $totalDamage;
$health = round($health);

//You is defeated?
if($health <= 0){
//Output defeated
echo "<br><i><b>You have been defeated!</b></i>";
$playerOutcome = "L";
$playerTurn = "O";
}
//You is alive
else {
//Output your health remaining
echo 'You now have <img src="img/health.gif"><b>'.$health.'</b> health.<br>';
$playerTurn = "Y";
}
}
}

}

echo '</td></tr></table>';

}


if ($playerOutcome == "W"){
//Player won, so calculate rewards.
$expGain = rand($level, $nmeLevel) * 2;
$goldGain = rand($level, $nmeTotal) / 2;

//Output rewards
echo '<font color=green><br><br><b>Your Health:</b> '.$health.'<img src="img/health.gif">';
echo '<br><b>Gold gained:</b> '.$goldGain;
echo '<br><b>EXP gained:</b> '.$expGain.'</font>';
}


if ($playerOutcome == "L"){
//Player won, so calculate rewards.
$expLost = rand($level, $nmeLevel) / 2;
$goldLost = rand($level, $nmeLevel) * 2;

//Output losses
echo '<font color=red><br><b>Gold lost:</b> '.$goldLost;
echo '<br><b>EXP lost:</b> '.$expLost.'</font>';
}

Display Player and Enemy Stats




All that was achieved by:

All that was achieved by:

//Output information about player and enemy header
echo '<table width="100%" align="center"><tbody><tr><td><b>You</b></td> <td> </td><td><b>'.$enemy.'</b></td></tr><tr><td>';

//Output player stats
echo '<b><center><u>Level '.$level.'</u></center></b>

<b><img src="img/healthBig.gif" alt="Health" />Health:</b> '.$health.'

<b><img src="img/mind.gif" alt="Mind" />Mind:</b> '.$mind.'

<b><img src="img/body.gif" alt="Body" />Body:</b> '.$body.'

<b><img src="img/soul.gif" alt="Soul" />Soul:</b> '.$soul.'

<b><img src="img/blocked.gif" alt="Defense" />Defense:</b> '.$defense.'

<b><img src="img/attack.gif" alt="Attack" /> Attack:</b> '.$attack.'

<b><img src="img/agility.gif" alt="Agility" /> Agility:</b> '.$agility;

//Output versus and enemy image
echo'
</td><td><center><img src="img/versus.gif" alt="Versus" />
<img src="img/'.$enemy.'.gif" alt="'.$enemy.'" /></center></td><td bgcolor="#ffffff" align="left">
';


//Display Enemy Stats
echo '<b><center><u>Level '.$level.'</u></center><u></u></b>

<b><img src="img/healthBig.gif" alt="Health" />Health:</b> '.$nmeHealth.'

<b><img src="img/mind.gif" alt="Mind" />Mind:</b> '.$nmeMind.'

<b><img src="img/body.gif" alt="Body" />Body:</b> '.$nmeBody.'

<b><img src="img/soul.gif" alt="Soul" />Soul:</b> '.$nmeSoul.'

<b><img src="img/blocked.gif" alt="Defense" />Defense:</b> '.$nmeDefense.'

<b><img src="img/attack.gif" alt="Attack" /> Attack:</b> '.$nmeAttack.'

<b><img src="img/agility.gif" alt="Agility" /> Agility:</b> '.$nmeAgility.'
</td></tr></tbody></table>';

Enemy Stats Roller

Enemies need stats that are relevant to the player's level. We are going to random generate an enemy based on similarly generated hero stats.

In the future this code will pull enemy name, level and image from a database. Players will be able to create enemies by giving them stats and images so that other players in the same level gap as their enemy can fight. Users should also be allowed to search for and target enemies outside of their level gap and other players (who are within their level gap).

Here is how it works:



// Enemy Generator appropriate for level
$rangeModifier = rand(0, $level);
$nmeMind = rand(4,$mind) + $rangeModifier;
$nmeBody = rand(4,$body) + $rangeModifier;
$nmeSoul = rand(4,$soul) + $rangeModifier;

//Generate Stats for enemy
$nmeTotal = ($nmeMind + $nmeBody + $nmeSoul);
$nmeLevel = ($nmeTotal) / 10;
$nmeLevel = round($nmeLevel);
$nmeHealth = ($nmeBody + $nmeSoul) * 5;
$nmeDefense = ($nmeTotal)/3 - 2;
$nmeDefense = round($nmeDefense);
$nmeAttack = ($nmeTotal)/3;
$nmeAttack = round($nmeAttack);
$nmeAgility = ($nmeBody + $nmeMind)/2;
$nmeAgility = round($nmeAgility);

//Generate enemy appropriate for level name and image
if ($level == 2){ $enemy = "Slime"; }
if ($level == 1){ $enemy = "Bug"; }
if ($level == 3){ $enemy = "Skeleton"; }



As you can see, the enemy is going to be around the player level, having randomly produced stats all within a close range to the player. The same script that generates a level 1-3 player can generate a level 1-3 enemy, or any level player and enemy combination for that matter.

Stats

These are the stats that I use (pretty much) from http://en.wikipedia.org/wiki/Tri-Stat_dX.

Stats
Characters in Tri-Stat have three main Stats:

Body: a measure of the character's physical prowess and health.
Mind: a measure of the character's mental capacity and intelligence.
Soul: a measure of the character's spirit and willpower.

Typical Stats range in levels from 1 to 20, although the Stats can go higher depending on the Power Level of the game. Levels of Stats are purchased with Character Points. All Stats cost two Character Points per level, requiring a minimum expenditure of two points per Stat. (Example: Having a Mind Stat of 6 would cost 12 points, two points each for the six stat points). An optional rule the GM can impose increases the point cost for Stats at incremental levels, so that high level Stats require more points to be increased to the next level.

Derived Values
Derived Values are determined by mathematical formulas based on the values of the character's Stats.

Attack Combat Value: (ACV) [(Body + Mind + Soul) / 3] which is the focus of all the character's Stats to determine their bonus to Hit an opponent during combat scenes.

Defense Combat Value: (DCV) [(Body + Mind + Soul) / 3 - 2] which is the character's ability to react against incoming attacks.

Health Points: [(Body + Soul) × 5] which is the amount of damage a character can withstand before they are knocked unconscious or killed. These are similar to hit points in other games.

Optional Derived Values:

Energy Points: [(Mind + Soul) × 5] an optional Stat used for fueling certain superpower Attributes. When a character runs out of Energy Points, they can no longer use that power.

Shock Value: [(Health Points) / 5] for more "realistic" combat scenes, when a character suffers their Shock Value in damage, there is a chance they can become stunned.


No, I've never played the original game, nor any other pen and paper RPG, so my implementation may be a complete butchering. Shock value was one thing I removed... some other names were changed during coding.

Here is what the PHP:


//stats roller
//This generates the stats for a character (the hero).
//This should be done on hero creation.

// Generate character three main stats
//Each stat is a random number between 4 and 12 to start with.
//This generates level 1 through 3 characters
//Each level is determined by every 10 stat points.
$mind = rand(4,12);
$body = rand(4,12);
$soul = rand(4,12);

//Generate additional stats
$total = ($mind + $body + $soul);
$level = ($total) / 10;
$level = round($level);
$health = ($body + $soul) * 5;
$defense = ($total)/3 - 2;
$defense = round($defense);
$attack = ($total)/3;
$attack = round($attack);
$agility = ($body + $mind)/2;
$agility = round($agility);

What is it?

MyRPGP is an idea I've had for a while now. I've often played role playing games online where the response is not real time and there is no server to deal with constantly keeping you updated. More recently, I've been exposed to social networking games like Mafia Wars on Facebook and an array of flash-based time consuming online RPG.

The main facets of these games is usually a time-based system of delay to prevent player progress. That concept is something I'm trying to overcome to bring a game to players that never puts them in a position where they are waiting for anything but their own imagination to catch up. Similarly, having to spend real money to get ahead in the game or spam friends constantly trying to gain an upper-hand is not something I'd ever program my self.

While I was searching around online for possible game rules to base an engine off of to handle characters, leveling, stats, battles, and every other possible aspect of the game from a mathematics stand-point (which, with lots of stats can be fairly difficult).

After much searching, I came across an easy 3 stat system that allowed the spawning of other stats (based on the three stats) and easy bracketing for levels and such.

In the creation of this game, I want there to easily be databases of "monsters" separated by level that generate stats based on their level. This way, a game master who is creating content (or all the users!) can add monsters to a database and all other players can challenge their monsters (guessing they are of the proper level gap).

Similarly, players are able to create their own characters that level up and gain stat points which can be allocated to develop individuals in desired directions.

During battle, the stats of players and monsters (or even players and players!) are rolled against each other mathematically until a victor is decided. There are complex mathematics that underlay the battle system so as to randomly introduce blocks, evasions and damage variations in to the equation from the influence of individual stats.

A response randomizer has also been developed to flavor the output of a battle and eventually make comments relevant to the outcome of a situation so the game seems more alive to the player.