package module.utility; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Map.Entry; import module.battle.BattleTask; import module.character.Group; import module.character.PlayerGroup; import module.character.api.ICharacter; import module.character.constants.CAttribute.attribute; import module.character.constants.CSpecialStatus; import module.character.constants.CStatus; import module.character.constants.CStatus.status; import module.command.CommandServer; import module.item.api.IEquipment; import module.item.api.IEquipment.EquipType; import module.item.api.IWeapon; import module.server.PlayerServer; public class BattleUtil { public static void deadMechanism(ICharacter target) { Group g = target.getMyGroup(); target.getMyGroup().getAtRoom().informRoom(target.getChiName() + "�˦a���_�F!\n"); if (g instanceof PlayerGroup) { target.getAttributeMap().get(attribute.HP).setCurrent(0); synchronized (g.getBattleTask().getTimeMap()) { g.getBattleTask().getTimeMap().get(target).setCurrent(0); } } g.getBattleTask().checkBattleEnd(); } public static boolean characterAttributeChange(ICharacter target, attribute attr, int value){ try { int max = target.getMaxAttribute(attr); int current = target.getCurrentAttribute(attr); if (current + value > max) current = max; else current += value; target.setCurrentAttribute(attr, current); return true; } catch (NullPointerException e){ // TODO: define null case? e.printStackTrace(); } return false; } public static boolean checkIfAbleToStartBattle(ICharacter src, ICharacter target){ Group g = src.getMyGroup(); if (g.getTalking() || g.getInEvent()){ CommandServer.informGroup(g, "�A������b���O�A���@�U�a�C\n"); } else if (target.getMyGroup().getTalking() || target.getMyGroup().getInEvent()){ CommandServer.informGroup(g, "�A���w������b���O�A���@�U�a�C\n"); } else return true; return false; } public static void handleBattleTaskBehavior(ICharacter src, ICharacter target){ if (src.getMyGroup() == target.getMyGroup()) return; Group gS = src.getMyGroup(); Group gT = target.getMyGroup(); if (gS.getInBattle()){ if (gT.getInBattle()){ if (gS == gT) return; // already in the same battle else { // TODO: define the battle merge mechanism } } else { // target group is not in battle gS.getBattleTask().addBattleOppositeGroup(gS, gT); } } else { if (gT.getInBattle()){ // src join target's battle gT.getBattleTask().addBattleOppositeGroup(gT, gS); } else { // both src & target group not in battle startNewBattle(gS, gT); } } } public static void attackMechanism(ICharacter src, ICharacter target){ StringBuffer buf = new StringBuffer(); IWeapon weapon = (IWeapon) src.getEquipment().get(EquipType.WEAPON); if (weapon != null){ buf.append(String.format("%s���ʤ⤤��%s�V%s��%s���h�A", src.getChiName(), weapon.getChiName(), target.getChiName(), target.getRandomBodyPart())); } else { buf.append(String.format("%s%s%s��%s�A", src.getChiName(), src.getBareHandAttackMessage(), target.getChiName(), target.getRandomBodyPart())); } // calculate dodge probability double hitRatio = 0.9; // TODO: define hitRatio if (weapon != null) hitRatio = weapon.getHitRatio(); hitRatio = CSpecialStatus.judgeHitRatioEffected(hitRatio, src.getSpecialStatusMap()); double speedDelta = (double) (src.getStatus(status.SPEED) - target.getStatus(status.SPEED)) / (double) target.getStatus(status.SPEED); // judge the dodge ratio speedDelta = CSpecialStatus.judgeDodgeRatioEffected(speedDelta, target.getSpecialStatusMap()); double dodgeRatio = 1 - hitRatio + speedDelta; if (dodgeRatio > 0.95) dodgeRatio = 0.95; if (dodgeRatio < 0) dodgeRatio = 0; if (PlayerServer.getRandom().nextDouble() > dodgeRatio){ // hit if (target.getAttributeMap().get(attribute.HP) != null) { int damage = attackDamage(src, target); if (damage > 0){ buf.append(String.format("��L�y��%d�I�ˮ`!\n", damage)); int current = target.getAttributeMap().get(attribute.HP) .getCurrent(); target.getAttributeMap().get(attribute.HP).setCurrent(current - damage); } else { // no damage buf.append("���o�ث¤O���L���@����b���̡C\n"); } } else { // no hp buf.append("���ݰ_�ӹ�L���@���_�@�ΡC\n"); } src.getMyGroup().getAtRoom().informRoom(buf.toString()); // weapon effect if (weapon != null){ weapon.onAttack(src, target); } if (target.isDown()) { BattleUtil.deadMechanism(target); } if (target.getMyGroup() instanceof PlayerGroup) { target.getMyGroup().getBattleTask() .updatePlayerStatus((PlayerGroup) target.getMyGroup()); } return; } else { // dodged buf.append("\n��" + target.getChiName() + "�ܧ֪��⨭�l������@�{�A���L�F����!\n"); } src.getMyGroup().getAtRoom().informRoom(buf.toString()); } private static int attackDamage(ICharacter src, ICharacter target){ int equipAtk = 0; for (Entry<EquipType, IEquipment> entry : src.getEquipment().entrySet()){ try { equipAtk += entry.getValue().getStatus() .get(CStatus.status.WEAPON_ATTACK); } catch (NullPointerException e){ // do nothing } } int atk = src.getStatus(status.STRENGTH) / 2 + equipAtk; //TODO: add weapon practice point // TODO: add critical hit mechanism int defense = target.getStatus(status.CONSTITUTION) + getCharPhysicalEquipDefense(target); int delta = atk - defense; if (delta < 0) delta = 0; // add random effect double rate = 100.0 + PlayerServer.getRandom().nextGaussian() * 5.0; double result = (double) delta * (rate / 100.0); return (int) result; } private static int getCharPhysicalEquipDefense(ICharacter target){ int defenseSum = 0; for (Entry<EquipType, IEquipment> entry : target.getEquipment().entrySet()){ try { defenseSum += entry.getValue().getStatus().get(CStatus.status.ARMOR); } catch (NullPointerException e){ // do nothing } } return defenseSum; } public static void startNewBattle(Group src, Group target){ Class<BattleTask> specialTaskClass = null; if (src.getSpecialBattle() != null) specialTaskClass = src.getSpecialBattle(); else if (target.getSpecialBattle() != null) specialTaskClass = src.getSpecialBattle(); if (specialTaskClass != null){ Class[] paramClass = new Class[] {Group.class, Group.class}; Object[] paramArray = new Object[] {src, target}; try { Constructor c = specialTaskClass.getConstructor(paramClass); c.newInstance(paramArray); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else new BattleTask(src, target); } public static String showStatusInBattle(ICharacter c){ if (c.getAttributeMap().containsKey(attribute.HP)){ int current, max; current = c.getCurrentAttribute(attribute.HP); max = c.getMaxAttribute(attribute.HP); double rate = (double) current / (double) max; String output = c.getChiName(); if (rate > 0.8) output += "�ݰ_�ӨS������ˡC"; else if (rate > 0.6) output += "���W���F�X�B�ˡA���L�٤�ê�ơC"; else if (rate > 0.4) output += "�I�l���áA���A���Ӧn�C"; else if (rate > 0.2) output += "�y��a�աA�n���H�ɳ��|�ˤU!"; else output += "���b���`��t�ä�A�V�O�M�D�@������!"; return output; } return null; } }