private function calcFirewallDamage(SR_Player $player, SR_Player $target, $level, $hits) { // echo "Calc damage with $hits hits\n"; $min = $level + 1; $max = $min + $hits * 1.0; return Shadowfunc::diceFloat($min, $max); }
public static function decideCombat(SR_Player $player, array $args) { echo __METHOD__ . PHP_EOL; $min = isset($args[0]) ? (int) $args[0] : 1.0; $max = isset($args[1]) ? (int) $args[1] : 1.0; return array('attack', Shadowfunc::diceFloat($min, $max, 2)); }
public function cast(SR_Player $player, SR_Player $target, $level, $hits, SR_Player $potion_player) { // echo "Casting Firebolt with level $level and $hits hits.\n"; $min = 1.0 + $level * 0.2; $max = $min + $level * 1.0 + $hits * 0.3; $damage = Shadowfunc::diceFloat($min, $max); return $this->spellDamageSingleTarget($player, $target, $level, '10040', $damage); }
public function cast(SR_Player $player, SR_Player $target, $level, $hits, SR_Player $potion_player) { echo "Casting " . $this->getName() . " with level {$level} and {$hits} hits.\n"; $min = 0.0; $max = $hits * 1.5; $sucked = Shadowfunc::diceFloat($min, $max, 1); $target->healMP(-$sucked); // $append = sprintf('%s lost %s MP.', $target->getName(), $sucked); $this->announceADV($player, $target, $level, '10090', $sucked); return true; }
public static function onASLSetRandom(SR_Player $player) { $data = SR_Player::$RACE_BASE[$player->getRace()]; $rand = Shadowfunc::diceFloat(0.8, 1.2, 2); $age = round($data['age'] * $rand); $age = Common::clamp($age, 18); $rand = Shadowfunc::diceFloat(0.8, 1.2, 2); $bmi = round($data['bmi'] * $rand * 1000); $height = round($data['height'] * $rand); return self::onASLSetCustom($player, $age, $bmi, $height); }
public function cast(SR_Player $player, SR_Player $target, $level, $hits, SR_Player $potion_player) { $min = $level + 1; $max = $min + $level / 4 + $hits / 10; $gain = Shadowfunc::diceFloat($min, $max); $oldhp = $target->getHP(); $maxhp = $target->getMaxHP(); $gain = $target->healHP($gain); $append = Shadowfunc::displayHPGain($oldhp, $gain, $maxhp); $this->announceADV($player, $target, $level, '10110', $append); return true; }
public function cast(SR_Player $player, SR_Player $target, $level, $hits, SR_Player $potion_player) { $wis = $potion_player->get('wisdom') * 30; $min = 20 + $level * 10; $max = 40 + $level * 20 + $wis; $seconds = rand($min, $max); $seconds = $this->lowerSpellIncrement($target, $seconds, 'frozen'); $target->busy($seconds * 10); $ef = Shadowfunc::diceFloat(0.1, $level, 1); $target->addEffects(new SR_Effect($seconds, array('frozen' => $ef), SR_Effect::MODE_ONCE_EXTEND)); $this->announceADV($player, $target, $level, '10050', $seconds, $ef); return true; }
/** * Poison the target. * @see SR_Weapon::onDealDamage() */ public function onDealDamage(SR_Player $player, SR_Player $target, $hits, $damage) { $biotech = Common::clamp($target->getVar('biotech'), 0, 15); $min = 0.1 - $biotech * 0.01; $max = 0.3 - $biotech * 0.02; $duration = rand(20, 40); $per_sec = Shadowfunc::diceFloat($min, $max, 2); if ($per_sec > 0) { $modifiers = array('hp' => $per_sec); $target->addEffects(new SR_Effect($duration, $modifiers)); $target->msg('5294', array(sprintf('%.02f', $per_sec), GWF_Time::humanDuration($duration))); } }
public function cast(SR_Player $player, SR_Player $target, $level, $hits, SR_Player $potion_player) { $wis = $potion_player->get('wisdom') * 30; $min = 5 + $level * 5; $max = 10 + $level * 10 + $wis; $seconds = rand($min, $max); $seconds = $this->lowerSpellIncrement($target, $seconds, 'frozen'); $target->busy($seconds * 10); $ef = Shadowfunc::diceFloat(0.1, $level, 1); $target->addEffects(new SR_Effect($seconds, array('frozen' => $ef), SR_Effect::MODE_ONCE_EXTEND)); $min = 0.5 + $level * 0.3; $max = $min + $level * 0.8 + $hits * 0.25; $damage = Shadowfunc::diceFloat($min, $max); return $this->spellDamageSingleTarget($player, $target, $level, '10040', $damage, $seconds); }
public function on_reward(SR_Player $player, array $args) { $bot = Shadowrap::instance($player); if (count($args) !== 1) { $bot->reply($this->lang($player, 'usage')); // $bot->reply('Usage: #reward <attribute|skill>. Will create a new rune.'); return false; } $f = strtolower($args[0]); if (isset(SR_Player::$SKILL[$f])) { $f = SR_Player::$SKILL[$f]; } if (isset(SR_Player::$ATTRIBUTE[$f])) { $f = SR_Player::$ATTRIBUTE[$f]; } if ($f === 'essence') { $min = 0.1; $max = 0.1; } elseif (in_array($f, SR_Player::$SKILL)) { $min = 0.2; $max = 0.6; } elseif (in_array($f, SR_Player::$ATTRIBUTE)) { $min = 0.4; $max = 0.8; } else { $bot->reply($this->lang($player, 'unknown')); // $bot->reply('This skill or attribute is unknown.'); return false; } $itemname = 'Rune_of_' . $f . ':' . Shadowfunc::diceFloat($min, $max, 1); if (false === ($item = SR_Item::createByName($itemname))) { $bot->reply($this->lang($player, 'broken')); // $bot->reply('My smith hammer is broken!'); return false; } $bot->reply($this->lang($player, 'cheers')); // $bot->reply('The dwarf cheers and get\'s to work.'); $bot->reply($this->lang($player, 'received', array($itemname))); // $bot->reply("You received ${itemname}."); $key = self::REWARD_RUNES; $player->giveItems(array($item)); $player->decreaseConst($key, -1); if (!$player->hasConst($key)) { $bot->reply($this->lang($player, 'rewarded')); // $bot->reply('You haved used all your #reward now.'); } return true; }
public function cast(SR_Player $player, SR_Player $target, $level, $hits, SR_Player $potion_player) { echo "Casting Vulcano with level {$level} and {$hits} hits.\n"; $this->announceADV($player, $target, $level); # Firebolt ads 0.20 per level $firebolt = $potion_player->getSpell('firebolt'); $firebolt = $firebolt === false ? 0 : $firebolt->getLevel($player); $firebolt = round($firebolt / 5, 1); $level += $firebolt; # Fireball ads 0.25 per level $fireball = $potion_player->getSpell('fireball'); $fireball = $fireball === false ? 0 : $fireball->getLevel($player); $fireball = round($fireball / 4, 1); $level += $fireball; # Firewall ads 0.3 per level $firewall = $potion_player->getSpell('firewall'); $firewall = $firewall === false ? 0 : $firewall->getLevel($player); $firewall = round($firewall * 0.3, 1); $level += $firewall; # Inaccurate $inaccuracy = Common::clamp(3 - $level * 0.1, 1); $targets = SR_Grenade::computeDistances($target, $inaccuracy); $p = $player->getParty(); $ep = $p->getEnemyParty(); $damage = array(); foreach ($targets as $data) { list($pid, $d) = $data; $target = $ep->getMemberByPID($pid); $d = Common::clamp($d, 1); $hits = $this->dice($potion_player, $target, $level); # Dice hits echo "!! Vulcano hits={$hits}, Distance={$d}"; $min = 1.0 + $level * 1.0; # Min damage is quite low $max = $min + $level + $hits * 1.2; # The max damage is min + hits $dmg = Shadowfunc::diceFloat($min, $max); $dmg /= $d / SR_Party::X_COORD_INC * 1.2; # Apply area reduction $dmg = round($dmg, 1); $damage[$pid] = $dmg; } $this->spellDamageMultiTargets($player, $damage, $level); return true; }
public static function alchemicFactory(SR_Player $player, $spellname, $level) { $ma = $player->get('magic'); $in = $player->get('intelligence'); $wi = $player->get('wisdom'); $alc = $player->get('alchemy'); # 10 - 80 percent randomness $randomness = 100 - ($wi + $alc * 2 + $in + $ma); $randomness = Common::clamp($randomness, 10, 80); $randomness = Shadowfunc::diceFloat(10, $randomness) * 0.01; # Dice! $minlevel = round($level - $level * $randomness, 1); $maxlevel = $level; $level = Shadowfunc::diceFloat($minlevel, $maxlevel, 1); $potion = SR_Item::createByName('AlchemicPotion'); $potion->addModifiers(array($spellname => $level, 'magic' => $player->getBase('magic'), 'intelligence' => $player->getBase('intelligence'), 'wisdom' => $player->getBase('wisdom'))); return $potion; }
public function cast(SR_Player $player, SR_Player $target, $level, $hits, SR_Player $potion_player) { $lev = $this->getLevel($player); $int = $potion_player->get('intelligence'); $wis = $potion_player->get('wisdom'); $min = 0.5; $min += $level * 0.2; $min += $wis * 0.2; $min += $int * 0.1; $min += $hits * 0.1; $max = $min * 2; $metres = Shadowfunc::diceFloat($min, $max, 2); $ep = $target->getParty(); $ep->movePlayer($target, false, $metres); $this->announceADV($player, $target, $level, '10020', $metres, $target->getY()); // $append = sprintf('%s got blown away %s metres and is now on position %s.', $target->getName(), $metres, $target->getY()); // $this->announceADV($player, $target, $level, $append); return true; }
public function cast(SR_Player $player, SR_Player $target, $level, $hits, SR_Player $potion_player) { echo "Casting Fireball with level {$level} and {$hits} hits.\n"; $this->announceADV($player, $target, $level); # Firebolt ads 0.20 per level $firebolt = $potion_player->getSpell('firebolt'); $firebolt = $firebolt === false ? 0 : $firebolt->getLevel($potion_player); $firebolt = round($firebolt / 5, 1); $level += $firebolt; # Inaccuracy $inaccuracy = Common::clamp(4 - $level * 0.15, 1); $targets = SR_Grenade::computeDistances($target, $inaccuracy); $p = $player->getParty(); $ep = $p->getEnemyParty(); $damage = array(); foreach ($targets as $data) { list($pid, $d) = $data; $target = $ep->getMemberByPID($pid); $d = Common::clamp($d, 1); $hits = $this->dice($potion_player, $target, $level); # Dice hits echo "!! Fireball hits={$hits}, Distance={$d}\n"; // $hits /= 2; # We take half.. // $hits /= ($d * 5); # And divide by distance // $hits = round($hits, 1); // echo " Fireball hits=$hits\n"; $min = 1.0 + $level * 0.5; # Min damage is quite low $max = $min + $level + $hits * 0.5; # The max damage is min + hits $dmg = Shadowfunc::diceFloat($min, $max); $dmg /= $d / SR_Party::X_COORD_INC * 1.4; # Apply area reduction $dmg = round($dmg, 1); // $player->message(sprintf("You have hit %s with %d hits, your damage is %.02f-%.02f, Distance from impact: %.02fm", $target->getName(), $hits, $min, $max, $d)); $damage[$pid] = $dmg; } $this->spellDamageMultiTargets($player, $damage, $level); return true; }
/** * Compute the distances to an explosion. * Imagaine the game like this * A * B E * F * CD * ---0m--- * @param SR_Player $target * @param unknown_type $radius * @param unknown_type $atk * @param unknown_type $atk_delta */ public static function computeDistances(SR_Player $target, $inaccuracy = 3) { $party = $target->getParty(); $members = $party->getMembers(); $coords = array(); foreach ($members as $m) { $m instanceof SR_Player; $coords[$m->getID()] = array($m->getX(), $m->getY()); } # Point of impact. $g_x = $coords[$target->getID()][0] + Shadowfunc::diceFloat(-$inaccuracy, +$inaccuracy); $g_y = $coords[$target->getID()][1] + Shadowfunc::diceFloat(-$inaccuracy, +$inaccuracy); // echo sprintf("Grenade has coords %.02f / %.02f\n", $g_x, $g_y); $back = array(); foreach ($coords as $uid => $data) { list($p_x, $p_y) = $data; $d = Shadowfunc::calcDistanceB($g_x, $g_y, $p_x, $p_y); $p = Shadowrun4::getPlayerByPID($uid); $back[] = array($uid, $d); // echo sprintf("%s has coords %.02f / %.02f (distance: %.02f)\n", $p->getName(), $p_x, $p_y, $d); } return $back; }
public function onHack(SR_Player $player, SR_Cyberdeck $cyberdeck) { $bot = Shadowrap::instance($player); if ($this->hasHacked($player)) { $bot->reply('Not again'); return false; } $pid = $player->getID(); $com = $player->get('computers'); $cyb = $cyberdeck->getCyberdeckLevel(); $atk = Shadowfunc::diceFloat(0, $com * 2.0 + $cyb * 2.0 + 2.0, 2); $com = $this->getComputerLevel($player); $def = Shadowfunc::diceFloat(0, $com * 3.2 + 3.0, 2); $hits = round(($atk - $def) * 10 - $this->getMinHits()); if ($hits > 0) { $this->hackers[$pid] = $this->getMaxAttempts(); return $this->onHacked($player, $hits); } return $this->onFailed($player, $hits, $this->hackers[$pid]); }
public function onConsume(SR_Player $player) { $oldhp = $player->getHP(); $gain = $player->healHP(Shadowfunc::diceFloat(1.0, 3.0, 1)); $player->getParty()->message($player, 'ate some bacon. ' . Shadowfunc::displayHPGain($oldhp, $gain, $player->getMaxHP())); }
public function getMovePerSecond() { return 1.5 + $this->get('quickness') * 0.25 + Shadowfunc::diceFloat(-0.2, +0.2, 1); }
public function on_steal(SR_Player $player, array $args) { $bot = Shadowrap::instance($player); if (count($args) !== 1) { $bot->reply(Shadowhelp::getHelp($player, 'steal')); return false; } if (false === ($item = $this->getStoreItem($player, $args[0]))) { $bot->rply('1140'); // $bot->reply('There is no such item here.'); return false; } $itemname = $item->getItemName(); # Steal difficulty $difficulty = $item->getItemLevel(); if ($difficulty < 0) { return $this->onStealOops($player, $itemname); } # Your skill $qu = $player->get('quickness'); $th = $player->get('thief'); $skill = $qu + $th * 2; # DEBUG printf("Dicing DIFF %.02f against SKILL %.02f ...\n", $difficulty, $skill); # Dice diff $min = $difficulty + 2; $max = $min * 2 + 1; $dice_diff = Shadowfunc::diceFloat($min, $max, 2); # Dice skill $min = 1; $max = $min + $skill + 1; $dice_skill = Shadowfunc::diceFloat($min, $max, 2); $bot->rply('5192', array($item->getItemName())); // $bot->reply(sprintf('You attempt to steal %s...', $item->getItemName())); # On succes we have a negative value. $difference = $dice_diff - $dice_skill; if ($difference < -$difficulty) { # Yay! return $this->onStealSuccess($player, $itemname); } elseif ($difference < 1) { # Nuts! return $this->onStealNothing($player, $itemname); } elseif ($difference > $difficulty * 2) { # Prison! return $this->onStealPrisoned($player, $itemname); } elseif ($difference > $difficulty) { # Police! return $this->onStealCombat($player, $itemname); } else { # Oops im beeing watched! :) return $this->onStealOops($player, $itemname); } $bot->reply('WRONG CODE IS WRONG!'); return false; }
private function onCrackLock(SR_Player $player, SR_Player $member) { $lvl = $this->getLockLevel(); $loc = $member->get('lockpicking'); $atk = Shadowfunc::diceFloat($loc, $loc * 2.0 + 1.0, 2); $def = Shadowfunc::diceFloat($lvl, $lvl * 1.5 + 2.0, 2); printf('%s tries to crack lock lvl %s with lockpicking %s. DEF:%s ... ATK: %s', $member->getName(), $lvl, $loc, $def, $atk) . PHP_EOL; if ($atk >= $def) { $this->onSetLockPlayer($member, 1); $this->onCrackedLock($player, $member); return true; } else { $this->onSetLockPlayer($member, 0); return false; } }
public function getLootXP() { return Shadowfunc::diceFloat(1, 2 + $this->getBase('level') / 5, 1) + $this->getNPCLootXP(); }
public static function randModifier(SR_Player $player, $level) { $luck = $player->get('luck'); $total = 0; $possible = array(); $level = intval($level + $luck * 2); foreach (self::getRuneData() as $data) { $minlvl = $data[self::RUNE_MIN_LEVEL]; if ($level < $minlvl) { continue; } $maxlvl = $data[self::RUNE_MAX_LEVEL]; $range = $maxlvl - $minlvl; # Percent of level $level = Common::clamp($level, 0, $maxlvl); $l = $level - $minlvl; $l = $l / $range; $dc = round($data[self::RUNE_DROP_CHANCE] * $l * 100); if ($dc < 1) { continue; } $possible[] = array($data, $dc); $total += $dc; } if (count($possible) === 0) { return false; } if (false === ($data = Shadowfunc::randomData($possible, $total, 0))) { return false; } $minlvl = $data[self::RUNE_MIN_LEVEL]; $maxlvl = $data[self::RUNE_MAX_LEVEL]; $range = $maxlvl - $minlvl; $l = $level - $minlvl; $l = $l / $range; $min = $data[self::RUNE_MIN_MODIFIER]; $max = $data[self::RUNE_MAX_MODIFIER]; $r = $max - $min; $max = $r * $l; $power = Shadowfunc::diceFloat($min, $min + $max, 2) * SR_Player::RUNE_MULTIPLIER; if ($power < 0.1) { return false; } // echo "RUNE POWER $min - $max: $power\n"; return array($data[self::RUNE_MODIFIER] => $power); }
public function on_split(SR_Player $player, array $args) { # Bailout $bot = Shadowrap::instance($player); if (count($args) !== 1) { $bot->reply(Shadowhelp::getHelp($player, 'split')); return false; } # Get Item if (false === ($rune = $player->getItem($args[0]))) { $bot->rply('1029'); // $bot->reply('You don`t have that item.'); return false; } $pid = $player->getID(); $itemname = $rune->getItemName(); $ditemname = $rune->displayFullName($player); $confirmed = isset(self::$SPLIT_CONFIRM[$pid]) && self::$SPLIT_CONFIRM[$pid] === $rune->getID(); unset(self::$SPLIT_CONFIRM[$pid]); if (!$rune instanceof SR_Rune) { $bot->rply('1166'); // $bot->reply('You can only split runes.'); return false; } $mods = array_merge($rune->getItemModifiersA($player), $rune->getItemModifiersB()); if (count($mods) < 2) { $bot->rply('1167'); // $bot->reply('This rune has only one modifier.'); return false; } # Check price $price = $this->calcSplitPrice($player, $rune->getItemPriceStatted()); $dp = Shadowfunc::displayNuyen($price); if (!$player->hasNuyen($price)) { $bot->rply('1063', array($dp, $player->displayNuyen())); // $player->message(sprintf('It would cost %s to split the %s, but you only have %s.', $dp, $itemname, $player->getNuyen())); return false; } # Confirm? if (!$confirmed) { self::$SPLIT_CONFIRM[$pid] = $rune->getID(); $bot->rply('5216', array($dp, $ditemname)); // $player->message(sprintf('It would cost %s to split the %s. Retype your command to confirm.', $dp, $itemname)); return true; } $runes = array(); $names = array(); $mods = array_merge($rune->getItemModifiersA($player), $rune->getItemModifiersB()); foreach ($mods as $k => $v) { $v /= 2; $v += Shadowfunc::diceFloat(0.0, $v / 2, 1); $v = round($v, 1); if ($v >= 0.1) { $name = "Rune_of_{$k}:{$v}"; $rune2 = SR_Item::createByName($name); $runes[] = $rune2; $names[] = $rune2->displayFullName($player); } } if (false === $rune->deleteItem($player)) { $bot->reply(sprintf('Cannot delete rune in %s line %s.', __FILE__, __LINE__)); return false; } if (count($runes) === 0) { $bot->rply('1168'); // $bot->reply(sprintf('The rune burned into dust while splitting it. You don\'t need to pay.')); return true; } if (false === $player->giveItems($runes)) { $bot->reply(sprintf('Cannot give items in %s line %s.', __FILE__, __LINE__)); return false; } if (false === $player->pay($price)) { $bot->reply(sprintf('Cannot pay price in %s line %s.', __FILE__, __LINE__)); return false; } return $bot->rply('5217', array($dp, $ditemname, GWF_Array::implodeHuman($names))); // return $bot->reply(sprintf('You pay %s and split your %s into %s.', $dp, $itemname, GWF_Array::implodeHuman($names))); }
public function onAttackB(SR_Player $player, $arg, $armor_type) { $p = $player->getParty(); $mc = $p->getMemberCount(); $ep = $p->getEnemyParty(); if (false === ($target = $this->getOffensiveTarget($player, $arg))) { return false; } $d = abs($player->getY() - $target->getY()); $d2 = Common::clamp($d - 2, 0); if ($d > $this->getItemRange()) { $player->getParty()->moveTowards($player, $target); return true; } if ($this instanceof SR_FireWeapon) { $this->increase('sr4it_ammo', -$this->getBulletsPerShot()); } # Bows are great for distance if ($this instanceof SR_Bow) { $d2 /= 4; } elseif ($this instanceof SR_MeleeWeapon) { $d2 = 0; } $busy = $player->busy($this->getRealAttackTime()); $mindmg = $player->get('min_dmg'); $maxdmg = $player->get('max_dmg'); $arm = $target->get($armor_type); $atk = round(Common::clamp($player->get('attack') - $d2 * 1.2, 1)); $def = $target->get('defense'); $hits = Shadowfunc::diceHits($mindmg, $arm, $atk, $def, $player, $target); $pname = $player->displayNameNB(); $tname = $target->displayNameNB(); $iname = $this->getName(); # Debug // Dog_Log::debug(sprintf('%s (ATK: %s HP: %s) vs. %s (DEF: %s HP: %s) = HITS: %s',$player->getName(),$atk,$player->getHP(),$target->getName(),$def,$target->getHP(),$hits)); # Miss if ($hits < 1) { $p->ntice('5230', array($pname, $tname, $iname, $busy)); $ep->ntice('5230', array($pname, $tname, $iname, $busy)); return true; // $msg .= ' but misses.'; } # Hit $damage = $hits * 0.1; $damage = round(Common::clamp($damage, 0.0, $maxdmg), 1); # Crit? $sharp = $player->getCritPermille(); if (rand(0, 1000) < $sharp) { $damage += Shadowfunc::diceFloat(1.0, $hits * 0.1 + 1.0, 1); $crit = 1; $bold = ""; } else { $crit = false; $bold = ''; } # No damage if ($damage <= 0) { $p->ntice('5231', array($pname, $tname, $iname, $busy)); $ep->ntice('5231', array($pname, $tname, $iname, $busy)); return true; // $msg .= sprintf(' but causes no damage.'); // $hpmsg = sprintf(' %s/%s HP left.', round($target->getHP(), 1), round($target->get('max_hp'), 1)); } $target->dealDamage($damage); # Special poison weapons $this->onDealDamage($player, $target, $hits, $damage); # Some damage if (false === $target->isDead()) { $p->ntice('5232', array($pname, $tname, $iname, $damage, $busy, $bold, $crit)); $ep->ntice('5233', array($pname, $tname, $iname, $damage, $target->getHP(), $target->getMaxHP(), $busy, $bold, $crit)); return true; } ########### # Killed! # ########### $xp = $target->isHuman() ? 0 : $target->getLootXP(); $nuyen = $target->getLootNuyen(); if ($player->isNPC()) { $target->resetXP(); } $target->giveNuyen(-$nuyen); $tl = $target->getBase('level'); $ploot = array(); $pxp = 0; foreach ($p->getMembers() as $member) { $member instanceof SR_Player; $lxp = $xp / $mc; $leveldiff = ($tl + 1) / ($member->getBase('level') + 1); $lxp *= $leveldiff; $lxp = round(Common::clamp($lxp, 0.01), 2); $pxp += $lxp; $xps[] = $lxp; $lny = round($nuyen / $mc, 2); $member->giveNuyen($lny); $member->msg('5234', array($pname, $tname, $iname, $damage, $busy, Shadowfunc::displayNuyen($lny), $lxp, $bold, $crit)); $member->giveXP($lxp); // $member->setOption(SR_Player::STATS_DIRTY, true); } $p->givePartyXP($pxp); $ep->ntice('5235', array($pname, $tname, $iname, $damage, $busy, $bold, $crit)); $target->gotKilledBy($player); return true; }
public function onConsume(SR_Player $player) { $oldhp = $player->getHP(); $gain = $player->healHP(Shadowfunc::diceFloat(0.2, 0.5, 1)); $player->getParty()->message($player, 'ate an apple. ' . Shadowfunc::displayHPGain($oldhp, $gain, $player->getMaxHP())); }