package com.asteria.net.message.impl;
import java.util.Optional;
import com.asteria.game.World;
import com.asteria.game.character.combat.Combat;
import com.asteria.game.character.combat.effect.CombatEffectType;
import com.asteria.game.character.combat.magic.CombatSpell;
import com.asteria.game.character.combat.magic.CombatSpells;
import com.asteria.game.character.player.Player;
import com.asteria.game.character.player.minigame.Minigame;
import com.asteria.game.character.player.minigame.MinigameHandler;
import com.asteria.game.location.Location;
import com.asteria.net.ByteOrder;
import com.asteria.net.ValueType;
import com.asteria.net.message.InputMessageListener;
import com.asteria.net.message.MessageBuilder;
/**
* The message sent from the client when a player attacks another player.
*
* @author lare96 <http://github.com/lare96>
*/
public final class AttackPlayerMessage implements InputMessageListener {
@Override
public void handleMessage(Player player, int opcode, int size, MessageBuilder payload) {
if (player.isDisabled())
return;
switch (opcode) {
case 249:
attackMagic(player, payload);
break;
case 73:
attackOther(player, payload);
break;
}
}
/**
* Attempts to attack a player with a magic spell.
*
* @param player
* the player to attempt to attack.
* @param payload
* the payloadfer for reading the sent data.
*/
private void attackMagic(Player player, MessageBuilder payload) {
int index = payload.getShort(true, ValueType.A);
int spellId = payload.getShort(true, ByteOrder.LITTLE);
Player victim = World.getPlayers().get(index);
CombatSpell spell = CombatSpells.getSpell(spellId).get().getSpell();
if (index < 0 || index > World.getPlayers().capacity() || spellId < 0 || !checkAttack(player, victim))
return;
player.setCastSpell(spell);
player.getCombatBuilder().attack(victim);
}
/**
* Attempts to attack a player with any other form of combat such as melee
* or ranged.
*
* @param player
* the player to attempt to attack.
* @param payload
* the payloadfer for reading the sent data.
*/
private void attackOther(Player player, MessageBuilder payload) {
int index = payload.getShort(true, ByteOrder.LITTLE);
Player victim = World.getPlayers().get(index);
if (index < 0 || index > World.getPlayers().capacity() || !checkAttack(player, victim))
return;
player.getCombatBuilder().attack(victim);
}
/**
* Determines if an attack can be made by the {@code attacker} on
* {@code victim}.
*
* @param attacker
* the player that is trying to attack.
* @param victim
* the player that is being targeted.
* @return {@code true} if an attack can be made, {@code false} otherwise.
*/
private boolean checkAttack(Player attacker, Player victim) {
if (victim == null || victim.equals(attacker))
return false;
if (!Location.inMultiCombat(attacker) && attacker.getCombatBuilder().isBeingAttacked() && attacker.getCombatBuilder()
.getLastAttacker() != victim) {
attacker.getMessages().sendMessage("You are already under attack!");
return false;
}
Optional<Minigame> optional = MinigameHandler.search(attacker);
if (!optional.isPresent()) {
if (!Location.inWilderness(attacker) || !Location.inWilderness(victim)) {
attacker.getMessages().sendMessage(
"Both you and " + victim.getFormatUsername() + " need to be in the wilderness" + " to fight!");
return false;
}
int combatDifference = Combat.combatLevelDifference(attacker.determineCombatLevel(), victim.determineCombatLevel());
if (combatDifference > attacker.getWildernessLevel() || combatDifference > victim.getWildernessLevel()) {
attacker.getMessages().sendMessage("Your combat level " + "difference is too great to attack that player here.");
return false;
}
if (!attacker.getCombatBuilder().isBeingAttacked() || attacker.getCombatBuilder().isBeingAttacked() && attacker
.getCombatBuilder().getLastAttacker() != victim && Location.inMultiCombat(attacker)) {
Combat.effect(attacker, CombatEffectType.SKULL);
}
} else {
if (!optional.get().canHit(attacker, victim))
return false;
}
return true;
}
}