public function __construct($Time, $Ability, $Actor, $DecreaseCooldown = false)
 {
     $this->Time = $Time;
     $this->Actor = $Actor;
     $this->Ability = $Ability;
     $Duration = AbilityItem::GetDuration($Ability);
     $Cooldown = AbilityItem::GetCooldown($Ability);
     $this->TimestampDone = $this->Time + AbilityItem::GetDuration($Ability);
     if ($DecreaseCooldown) {
         $Cooldown -= $Cooldown * AbilityItem::GetMultiplier(Enums\EAbility::Support_DecreaseCooldowns);
     }
     $this->TimestampCooldown = $this->Time + $Cooldown;
 }
示例#2
0
 /**
  *
  * @return bool Returns true if ability has been successfully used, false otherwise.
  */
 public static function HandleAbility($Game, $Lane, $Player, $Ability, $Deactivate = false)
 {
     $AbilityMultiplier = self::GetMultiplier($Ability->GetAbility());
     switch ($Ability->GetAbility()) {
         case Enums\EAbility::Offensive_HighDamageOneTarget:
             if (!$Deactivate) {
                 $Enemy = $Lane->GetEnemy($Player->GetTarget());
                 if ($Enemy === null || $Enemy->IsDead()) {
                     return false;
                 }
                 $Damage = $Enemy->GetMaxHp();
                 if ($Enemy->GetType() === Enums\EEnemyType::Boss) {
                     $Damage *= self::GetMultiplierBoss(Enums\EAbility::Offensive_HighDamageOneTarget);
                 } else {
                     $Damage *= $AbilityMultiplier;
                 }
                 $Player->Stats->AbilityDamageDealt += $Damage;
                 $Enemy->AbilityDamageTaken += $Damage;
             }
             break;
         case Enums\EAbility::Offensive_DamageAllTargets:
             if (!$Deactivate) {
                 $Enemies = $Lane->GetAliveEnemies();
                 if (empty($Enemies)) {
                     return false;
                 }
                 foreach ($Enemies as $Enemy) {
                     $Damage = $Enemy->GetMaxHp() * $AbilityMultiplier;
                     $Player->Stats->AbilityDamageDealt += $Damage;
                     $Enemy->AbilityDamageTaken += $Damage;
                 }
             }
             break;
         case Enums\EAbility::Item_Resurrection:
             if (!$Deactivate) {
                 $NotUsed = true;
                 $PlayersInLane = $Game->GetPlayersInLane($Lane->GetLaneId());
                 foreach ($PlayersInLane as $PlayerInLane) {
                     if ($PlayerInLane->IsDead()) {
                         $NotUsed = false;
                         $PlayerInLane->Respawn();
                     }
                 }
                 if ($NotUsed) {
                     return false;
                 }
             }
             break;
         case Enums\EAbility::Item_KillTower:
             if (!$Deactivate) {
                 $Enemy = $Lane->GetEnemy($Player->GetTarget());
                 if ($Enemy === null || $Enemy->IsDead()) {
                     return false;
                 }
                 if ($Enemy->GetType() !== Enums\EEnemyType::Tower) {
                     return false;
                 }
                 $Enemy->SetHp(1);
             }
             break;
         case Enums\EAbility::Item_KillMob:
             if (!$Deactivate) {
                 $Enemy = $Lane->GetEnemy($Player->GetTarget());
                 if ($Enemy === null || $Enemy->IsDead()) {
                     return false;
                 }
                 if ($Enemy->GetType() === Enums\EEnemyType::Boss) {
                     $MaxPercentage = $AbilityMultiplier;
                     $Percentage = $MaxPercentage + lcg_value() * abs($MaxPercentage - 0.01);
                     # 1% - 5%
                     $Damage = $Enemy->GetMaxHp() * $Percentage;
                     $Player->Stats->AbilityDamageDealt += $Damage;
                     $Enemy->AbilityDamageTaken += $Damage;
                 } else {
                     $Enemy->SetHp(1);
                 }
             }
             break;
         case Enums\EAbility::Item_IncreaseCritPercentagePermanently:
             if (!$Deactivate) {
                 $Player->GetTechTree()->IncreaseCritPercentage($AbilityMultiplier);
                 $Lane->AddActivePlayerAbility(new ActiveAbility($Game->Time, Enums\EAbility::Support_IncreaseCritPercentage, $Player->PlayerName, $Lane->HasActivePlayerAbilityDecreaseCooldowns()));
             }
             break;
         case Enums\EAbility::Item_IncreaseHPPermanently:
             if (!$Deactivate) {
                 $Player->GetTechTree()->IncreaseHpMultiplier($AbilityMultiplier);
                 $Player->GetTechTree()->RecalulateUpgrades();
                 $Lane->AddActivePlayerAbility(new ActiveAbility($Game->Time, Enums\EAbility::Support_Heal, $Player->PlayerName, $Lane->HasActivePlayerAbilityDecreaseCooldowns()));
             }
             break;
         case Enums\EAbility::Item_GoldForDamage:
             if (!$Deactivate) {
                 $Enemy = $Lane->GetEnemy($Player->GetTarget());
                 if ($Player->GetGold() === 0 || $Enemy === null || $Enemy->IsDead()) {
                     return false;
                 }
                 $MaxPercentage = $AbilityMultiplier;
                 $Percentage = $MaxPercentage + lcg_value() * abs($MaxPercentage - 0.01);
                 # 1% - 10%
                 $Player->DecreaseGold($Player->GetGold() * $MaxPercentage);
                 # 10%
                 $Damage = $Enemy->GetMaxHp() * $Percentage;
                 $Player->Stats->AbilityDamageDealt += $Damage;
                 $Enemy->AbilityDamageTaken += $Damage;
             }
             break;
         case Enums\EAbility::Item_GiveGold:
             if (!$Deactivate) {
                 $Player->IncreaseGold($AbilityMultiplier * pow(10, max(0, floor(log10($Game->GetLevel())) - 1)));
                 $Lane->AddActivePlayerAbility(new ActiveAbility($Game->Time, Enums\EAbility::Support_IncreaseGoldDropped, $Player->PlayerName, $Lane->HasActivePlayerAbilityDecreaseCooldowns()));
             }
             break;
         case Enums\EAbility::Item_GiveRandomItem:
             if (!$Deactivate) {
                 $PlayersInLane = $Game->GetPlayersInLane($Lane->GetLaneId());
                 foreach ($PlayersInLane as $PlayerInLane) {
                     if (!$PlayerInLane->IsDead()) {
                         $PlayerInLane->AddLoot($Game->Time, AbilityItem::GetRandomAbilityItem());
                     }
                 }
             }
             break;
         case Enums\EAbility::Item_SkipLevels:
             if (!$Deactivate) {
                 $Game->WormholeCount++;
             }
             break;
     }
     return true;
 }
示例#3
0
 public function Update($SecondsPassed = false)
 {
     $this->Time = time();
     if (!$this->IsRunning()) {
         Server::GetLogger()->debug('Game #' . $this->GameId . ' is not running, canceling update');
         return;
     }
     Server::GetLogger()->debug('Updating game #' . $this->GameId);
     $SecondPassed = $SecondsPassed !== false && $SecondsPassed > 0;
     $LaneDps = [0 => 0, 1 => 0, 2 => 0];
     foreach ($this->Players as $Player) {
         $Player->ClearLoot($this->Time);
         $Player->CheckActiveAbilities($this);
         if ($SecondPassed && !$Player->IsDead()) {
             // Deal DPS damage to current target
             $Lane = $this->Lanes[$Player->GetCurrentLane()];
             $Enemy = $Lane->GetEnemy($Player->GetTarget());
             if ($Enemy === null || $Enemy->IsDead()) {
                 $Enemy = $Lane->GetAliveEnemy();
                 if ($Enemy !== null) {
                     $Player->SetTarget($Enemy->GetPosition());
                 }
             }
             if ($Enemy !== null) {
                 $DealtDpsDamage = $Player->GetTechTree()->GetDps() * $Player->GetTechTree()->GetExtraDamageMultipliers($this->Lanes[$Player->GetCurrentLane()]->GetElement()) * $this->Lanes[$Player->GetCurrentLane()]->GetDamageMultiplier() * $SecondsPassed;
                 if ($this->Lanes[$Player->GetCurrentLane()]->HasActivePlayerAbilityMaxElementalDamage()) {
                     $DealtDpsDamage *= $Player->GetTechTree()->GetHighestElementalMultiplier();
                 }
                 if ($Player->GetCritDamage() > 0) {
                     $DealtDpsDamage *= $Player->GetTechTree()->GetDamageMultiplierCrit();
                     $Player->Stats->CritDamageDealt += $DealtDpsDamage;
                     $Player->CritDamage = 0;
                 }
                 $Player->Stats->DpsDamageDealt += $DealtDpsDamage;
                 $Enemy->DpsDamageTaken += $DealtDpsDamage;
                 if ($DealtDpsDamage > 0) {
                     Server::GetLogger()->debug('Player ' . $Player->PlayerName . ' (#' . $Player->GetAccountId() . ')' . ' did ' . $DealtDpsDamage . ' DPS damage to enemy #' . $Enemy->GetId());
                 }
                 foreach ($Player->LaneDamageBuffer as $LaneId => $LaneDamage) {
                     $LaneDps[$LaneId] += $LaneDamage / $SecondsPassed;
                     // TODO: This is damage done by clicks, not per second, remove or keep?
                     $Player->LaneDamageBuffer[$LaneId] = 0;
                 }
                 $LaneDps[$Player->GetCurrentLane()] += $Player->GetTechTree()->GetDps() * $SecondsPassed;
                 #TODO: $DealtDpsDamage?
             }
         }
         if ($Player->IsDead() && $Player->CanRespawn($this->Time, true)) {
             // Respawn player
             $Player->Respawn();
         }
     }
     // Loop through lanes and deal damage etc
     $DeadLanes = 0;
     foreach ($this->Lanes as $LaneId => $Lane) {
         if ($SecondPassed) {
             # TODO: Apply this in Lane::CheckActivePlayerAbilities instead?
             $ReflectDamageMultiplier = $Lane->GetReflectDamageMultiplier();
             $NapalmDamageMultiplier = $Lane->GetNapalmDamageMultiplier();
         }
         $DeadEnemies = 0;
         $EnemyCount = count($Lane->Enemies);
         $EnemyDpsDamage = 0;
         foreach ($Lane->Enemies as $Enemy) {
             if ($Enemy->IsDead()) {
                 if ($Enemy->GetDpsHpDifference() > 0) {
                     // Find next enemy to deal the rest of the DPS damage to
                     $NextEnemy = $Lane->GetAliveEnemy();
                     if ($NextEnemy !== null) {
                         Server::GetLogger()->debug('Enemy #' . $Enemy->GetId() . ' is dead. Passing on ' . $Enemy->GetDpsHpDifference() . ' DPS damage to enemy #' . $NextEnemy->GetId());
                         $NextEnemy->DpsDamageTaken += $Enemy->GetDpsHpDifference();
                     }
                 }
                 $DeadEnemies++;
             } else {
                 if ($SecondPassed) {
                     # TODO: Apply this in Lane::CheckActivePlayerAbilities instead?
                     # TODO: Check if $ReflectDamageMultiplier is 0.5% or 50%, 0.5% would make more sense if it stacks..
                     if ($ReflectDamageMultiplier > 0) {
                         $Enemy->AbilityDamageTaken += $Enemy->GetHp() * $ReflectDamageMultiplier * $SecondsPassed;
                     }
                     if ($NapalmDamageMultiplier > 0) {
                         $Damage = $Enemy->GetMaxHp() * $NapalmDamageMultiplier * $SecondsPassed;
                         $Enemy->AbilityDamageTaken += $Damage;
                     }
                 }
                 $Enemy->Hp -= $Enemy->DpsDamageTaken;
                 if ($Enemy->GetDpsHpDifference() > 0) {
                     // Find next enemy to deal the rest of the DPS damage to
                     $NextEnemy = $Lane->GetAliveEnemy();
                     if ($NextEnemy !== null) {
                         Server::GetLogger()->debug('Enemy #' . $Enemy->GetId() . ' is dead. Passing on ' . $Enemy->GetDpsHpDifference() . ' DPS damage to enemy #' . $NextEnemy->GetId());
                         $NextEnemy->DpsDamageTaken += $Enemy->GetDpsHpDifference();
                     }
                 }
                 $Enemy->Hp -= $Enemy->ClickDamageTaken;
                 $Enemy->Hp -= $Enemy->AbilityDamageTaken;
                 if ($Enemy->IsDead()) {
                     $this->IncreaseEnemiesKilled($Enemy);
                     $Enemy->SetHp(0);
                     $DeadEnemies++;
                     $EnemyGold = $Enemy->GetGold() * $Lane->GetEnemyGoldMultiplier();
                     Server::GetLogger()->debug('Enemy #' . $Enemy->GetId() . ' is dead. Giving ' . $EnemyGold . ' gold (Multiplier: ' . $Lane->GetEnemyGoldMultiplier() . ') to players in lane #' . $Lane->GetLaneId());
                     $Lane->GiveGoldToPlayers($this, $EnemyGold);
                 } else {
                     $EnemyDpsDamage += $Enemy->GetDps();
                 }
             }
             $Enemy->DpsDamageTaken = 0;
             $Enemy->ClickDamageTaken = 0;
             $Enemy->AbilityDamageTaken = 0;
             if ($Enemy->HasTimer() && $Enemy->IsTimerEnabled() && $Enemy->HasTimerRanOut($SecondsPassed)) {
                 switch ($Enemy->GetType()) {
                     case Enums\EEnemyType::Tower:
                         if ($Enemy->IsDead()) {
                             continue;
                         }
                         // Revive dead mobs in the lane if the tower timer ran out
                         Server::GetLogger()->debug('Respawn timer has ran out in lane #' . $Lane->GetLaneId() . ', reviving dead mobs in the lane');
                         foreach ($Lane->GetDeadEnemies(Enums\EEnemyType::Mob) as $DeadEnemy) {
                             $DeadEnemy->ResetHp();
                         }
                         break;
                     case Enums\EEnemyType::MiniBoss:
                         if (!$Enemy->IsDead()) {
                             continue;
                         }
                         // Revive dead miniboss if he's dead and the timer ran out
                         Server::GetLogger()->debug('Respawn timer has ran out for miniboss #' . $Enemy->GetId() . ' in lane #' . $Lane->GetLaneId() . ', reviving dead miniboss');
                         $Enemy->ResetHp();
                         break;
                     case Enums\EEnemyType::TreasureMob:
                         if ($Enemy->IsDead()) {
                             continue;
                         }
                         // Kill the treasure mob and set gold to 0 if the timer (lifetime) ran out
                         Server::GetLogger()->debug('Treasure mob #' . $Enemy->GetId() . ' timer has ran out in lane #' . $Lane->GetLaneId() . ', killing treasure mob');
                         $Enemy->SetHp(0);
                         $Enemy->SetGold(0);
                         $Enemy->DisableTimer();
                         $this->AddChatEntry('server', '', 'You were too slow to kill the treasure, it has despawned');
                         break;
                 }
                 $Enemy->ResetTimer();
             }
         }
         $DeadLanes += $DeadEnemies === count($Lane->Enemies) ? 1 : 0;
         // Deal damage to players in lane
         $PlayersInLane = [];
         foreach ($this->Players as $Player) {
             if ($Player->GetCurrentLane() === $LaneId) {
                 $PlayersInLane[] = $Player;
                 if ($Player->IsInvulnerable()) {
                     continue;
                 }
                 if ($SecondPassed && !$Player->IsDead()) {
                     $EnemyDamage = $EnemyDpsDamage * $SecondsPassed;
                     $PlayerHp = $Player->Hp - $EnemyDamage;
                     if ($PlayerHp > 0) {
                         $Player->Stats->DamageTaken += $EnemyDamage;
                         $Player->Hp = $PlayerHp;
                     } else {
                         $Player->Stats->DamageTaken += $Player->Hp;
                         $Player->Hp = 0;
                         $Player->Kill($this->Time);
                     }
                 }
             }
         }
         $Lane->Dps = $LaneDps[$LaneId];
         $Lane->CheckActivePlayerAbilities($this, $SecondsPassed);
         $Lane->UpdateHpBuckets($this->Time, $PlayersInLane);
     }
     if ($DeadLanes === 3) {
         if ($this->WormholeCount > 0) {
             if ($this->IsGoldHelmBossLevel()) {
                 $this->WormholeCount *= 10;
             }
             $this->Level += $this->WormholeCount;
             $BadgePoints = Util::FloorToMultipleOf(10, $this->WormholeCount * 0.1);
             $AbilityGold = AbilityItem::GetGoldMultiplier(Enums\EAbility::Item_SkipLevels);
             $Players = $this->GetPlayers();
             foreach ($Players as $Player) {
                 $Player->IncreaseGold($AbilityGold * $this->WormholeCount);
                 # TODO: Is gold stackable as well?
                 if ($BadgePoints > 0) {
                     $Player->GetTechTree()->IncreaseBadgePoints($BadgePoints);
                 }
             }
             $this->AddChatEntry('server', '', 'Skipped ' . number_format($this->WormholeCount) . ' level' . ($this->WormholeCount === 1 ? '' : 's'));
             $this->WormholeCount = 0;
             foreach ($this->Lanes as $Lane) {
                 $Lane->RemoveActiveWormholes();
             }
         }
         $this->GenerateNewLevel();
     }
 }
示例#4
0
 public function AddAbilityItem($AbilityId, $Quantity = 1)
 {
     if (AbilityItem::GetType($AbilityId) !== Enums\EAbilityType::Item) {
         $Upgrade = $this->GetUpgradeByAbility($AbilityId);
         if ($Upgrade !== null && $Upgrade->GetLevel() === 0) {
             $Upgrade->IncreaseLevel();
         }
         $this->UnlockAbility($AbilityId);
         return;
     }
     if (!isset($this->AbilityItems[$AbilityId])) {
         $this->AbilityItems[$AbilityId] = ['ability' => $AbilityId, 'quantity' => 1];
     } else {
         $this->AbilityItems[$AbilityId]['quantity']++;
     }
 }
示例#5
0
 public function CheckActiveAbilities(Game $Game)
 {
     foreach ($this->ActiveAbilities as $Key => $ActiveAbility) {
         if ($ActiveAbility->IsCooledDown($Game->Time)) {
             AbilityItem::HandleAbility($Game, $Game->GetLane($this->GetCurrentLane()), $this, $ActiveAbility, true);
             $this->RemoveActiveAbility($Key);
         }
     }
 }
示例#6
0
 private function GetActivePlayerAbilityMultipler($AbilityId)
 {
     # TODO: @Contex: Create an additional array that can cache the result? Instead of looping every single time...
     $Multiplier = 0;
     foreach ($this->ActivePlayerAbilities as $ActivePlayerAbility) {
         if ($ActivePlayerAbility->GetAbility() === $AbilityId) {
             $Multiplier += AbilityItem::GetMultiplier($ActivePlayerAbility->GetAbility());
         }
     }
     return $Multiplier;
 }