Added TurretAI

- Added vehicles
- Tweaked AI to consider opposite faction-aligned Installationobjects
enemies
- Added turret shooting at NPCs
- Debugged actors
This commit is contained in:
CharonInferar
2014-07-16 16:52:36 +02:00
parent cc28f80394
commit db036574b7
30 changed files with 3140 additions and 268 deletions
+372 -2
View File
@@ -54,6 +54,7 @@ import resources.datatables.Elemental;
import resources.datatables.Posture;
import resources.datatables.WeaponType;
import resources.objects.creature.CreatureObject;
import resources.objects.installation.InstallationObject;
import resources.objects.mission.MissionObject;
import resources.objects.player.PlayerObject;
import resources.objects.tangible.TangibleObject;
@@ -240,6 +241,148 @@ public class CombatService implements INetworkDispatch {
}
}
}
public void doCombatForInstallation(final InstallationObject attacker, final TangibleObject target, final WeaponObject weapon, final CombatCommand command, final int actionCounter) {
if(target instanceof CreatureObject) if(((CreatureObject) target).getPosture() == Posture.Incapacitated || ((CreatureObject) target).getPosture() == Posture.Dead) return;
boolean success = true;
// if((command.getAttackType() == 0 || command.getAttackType() == 1 || command.getAttackType() == 3) && !attemptCombat(attacker, target))
// success = false;
// if(success && !applySpecialCost(attacker, weapon, command))
// success = false;
if(!success) {
IoSession session = attacker.getClient().getSession();
CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectId(), actionCounter);
session.write(new ObjControllerMessage(0x0B, commandRemove).serialize());
StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC(), CRC.StringtoCRC(command.getCooldownGroup()), -1);
session.write(new ObjControllerMessage(0x0B, startTask).serialize());
return;
}
final Point3D targetPos = target.getPosition();
final SWGObject targetParent = target.getContainer();
if(command.getDelayAttackParticle().length() > 0 || command.getInitialAttackDelay() > -1) {
if(command.getInitialAttackDelay() > 0) {
if(command.getDelayAttackParticle().length() > 0)
target.notifyObservers(new PlayClientEffectLocMessage(command.getDelayAttackParticle(), target.getPlanet().getName(), target.getWorldPosition()), true);
try {
Thread.sleep((long) command.getInitialAttackDelay() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if(command.getInitialAttackDelay() <= 0 && command.getDelayAttackInterval() > 0 && command.getDelayAttackLoops() <= 1) {
try {
Thread.sleep((long) command.getDelayAttackInterval() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(command.getDelayAttackParticle().length() > 0)
target.notifyObservers(new PlayClientEffectLocMessage(command.getDelayAttackParticle(), target.getPlanet().getName(), target.getWorldPosition()), true);
}
if(command.getDelayAttackLoops() > 1) {
final ScheduledFuture<?> task = scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
if(command.getDelayAttackParticle().length() > 0)
target.notifyObservers(new PlayClientEffectLocMessage(command.getDelayAttackParticle(), target.getPlanet().getName(), target.getWorldPosition()), true);
if(command.getAttackType() == 1)
doSingleTargetCombatForInstallation(attacker, target, weapon, command, actionCounter);
//else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3)
//doAreaCombat(attacker, targetPos, weapon, command, actionCounter, targetParent);
} catch (Exception e) {
e.printStackTrace();
}
}
}, 0, (long) (command.getDelayAttackInterval() * 1000), TimeUnit.MILLISECONDS);
scheduler.schedule(new Runnable() {
@Override
public void run() {
try {
task.cancel(true);
} catch (Exception e) {
e.printStackTrace();
}
}
}, (long) ((command.getDelayAttackInterval() * 1000) * command.getDelayAttackLoops()), TimeUnit.MILLISECONDS);
return;
} else {
if(command.getAttackType() == 1)
doSingleTargetCombatForInstallation(attacker, target, weapon, command, actionCounter);
//else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3)
//doAreaCombat(attacker, targetPos, weapon, command, actionCounter, targetParent);
}
} else {
if(command.getAttackType() == 1)
doSingleTargetCombatForInstallation(attacker, target, weapon, command, actionCounter);
//else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3)
//doAreaCombat(attacker, target, weapon, command, actionCounter);
}
if(target instanceof CreatureObject)
{
CreatureObject creature = (CreatureObject)target;
if(creature.getPosture() == Posture.Incapacitated || creature.getPosture() == Posture.Dead)
{
for (TangibleObject defender : new ArrayList<TangibleObject>(creature.getDefendersList()))
{
defender.removeDefender(creature);
creature.removeDefender(defender);
}
if(((CreatureObject) target).getPlayerObject() == null)
{
target.setKiller(attacker);
scheduler.schedule(new Runnable()
{
@Override
public void run()
{
try {
core.objectService.destroyObject(target);
} catch (Exception e) {
e.printStackTrace();
}
}
}, 2, TimeUnit.MINUTES);
}
}
}
else if(target instanceof TangibleObject)
{
if(target.getConditionDamage() == target.getMaximumCondition())
{
for(TangibleObject defender : target.getDefendersList()) defender.removeDefender(target);
core.objectService.destroyObject(target);
}
}
}
private void doAreaCombat(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) {
if(target instanceof CreatureObject) {
@@ -313,6 +456,24 @@ public class CombatService implements INetworkDispatch {
}
private void doSingleTargetCombatForInstallation(InstallationObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) {
if(target instanceof CreatureObject) {
doSingleTargetCombatForInstallation(attacker, (CreatureObject) target, weapon, command, actionCounter);
return;
}
float damage = calculateDamageForInstallation(attacker, target, weapon, command);
if(damage > 0)
applyDamageForInstallation(attacker, target, (int) damage);
sendCombatPacketsForInstallation(attacker, target, weapon, command, actionCounter, damage, 0, HitType.HIT);
if(FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName() + ".py"))
core.scriptService.callScript("scripts/commands/combat/", command.getCommandName(), "run", core, attacker, target, damage);
}
private void applyDamage(CreatureObject attacker, TangibleObject target, int damage) {
target.setConditionDamage(target.getConditionDamage() + damage);
@@ -336,9 +497,127 @@ public class CombatService implements INetworkDispatch {
event.attacker = attacker;
event.damage = damage;
target.getEventBus().publish(event);
System.out.println("APPLY DAMAGE2");
attacker.setTefTime(300000);
}
private void applyDamageForInstallation(InstallationObject attacker, TangibleObject target, int damage) {
target.setConditionDamage(target.getConditionDamage() + damage);
if (target.getOption(Options.MOUNT)) {
core.mountService.damage((CreatureObject) target);
}
if (target instanceof CreatureObject){
CreatureObject targetCreature = (CreatureObject)target;
if (targetCreature.getCalledPet()!=null) {
AIActor petActor = (AIActor) targetCreature.getCalledPet().getAttachment("AI");
if (petActor!=null){
petActor.addDefender(attacker);
DevLog.debugout("Charon", "Pet AI", "applyDamage addDefender");
}
}
}
DamageTaken event = events.new DamageTaken();
event.attacker = attacker;
event.damage = damage;
target.getEventBus().publish(event);
//attacker.setTefTime(300000);
}
private void applyDamageForInstallation(InstallationObject attacker, CreatureObject target, int damage) {
if(target.getHealth() - damage <= 0 && target.getSlottedObject("ghost") != null) {
if(target.hasBuff("incapWeaken")) {
AIActor aiActor = (AIActor)attacker.getAttachment("AI");
deathblowPlayerFromInstallation(attacker, target);
return;
}
AIActor aiActor = (AIActor)attacker.getAttachment("AI");
if (aiActor.getMobileTemplate().isDeathblow()){
deathblowPlayerFromInstallation(attacker, target);
return;
}
synchronized(target.getMutex()) {
if (core.mountService.isMounted(target)) {
core.mountService.dismount(target, (CreatureObject) target.getContainer());
}
target.setHealth(1);
target.setPosture(Posture.Incapacitated);
target.setTurnRadius(0);
target.setSpeedMultiplierBase(0);
}
ScheduledFuture<?> incapTask = scheduler.schedule(() -> {
synchronized(target.getMutex()) {
try {
if(target.getPosture() != 13)
return;
target.setPosture(Posture.Upright);
target.setTurnRadius(1);
target.setSpeedMultiplierBase(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}, target.getIncapTimer(), TimeUnit.SECONDS);
target.setIncapTask(incapTask);
core.buffService.addBuffToCreature(target, "incapWeaken", target);
if(target.getSlottedObject("ghost") != null && attacker.getSlottedObject("ghost") != null) {
target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_incap", "TT", attacker.getCustomName()), DisplayType.Broadcast);
//attacker.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_target_incap", "TT", target.getCustomName()), DisplayType.Broadcast);
} else {target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_incap", "TT", "@" + attacker.getStfFilename() + ":" + attacker.getStfName()), DisplayType.Broadcast); }
return;
} else if(target.getHealth() - damage <= 0 && target.getAttachment("AI") != null) {
synchronized(target.getMutex()) {
target.setHealth(0);
target.setPosture(Posture.Dead);
}
attacker.removeDefender(target);
target.removeDefender(attacker);
return;
}
synchronized(target.getMutex()) {
target.setHealth(target.getHealth() - damage);
}
if (target instanceof CreatureObject){
CreatureObject targetCreature = (CreatureObject)target;
if (targetCreature.getCalledPet()!=null) {
AIActor petActor = (AIActor) targetCreature.getCalledPet().getAttachment("AI");
if (petActor!=null){
petActor.addDefender(attacker);
DevLog.debugout("Charon", "Pet AI", "applyDamage addDefender");
}
}
}
if (target.getPosture()!=13){
DamageTaken event = events.new DamageTaken();
event.attacker = attacker;
event.damage = damage;
target.getEventBus().publish(event);
}
}
private void doAreaCombat(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) {
@@ -455,6 +734,27 @@ public class CombatService implements INetworkDispatch {
sendCombatPackets(attacker, target, weapon, command, actionCounter, damage, 0, HitType.HIT);
}
private void doSingleTargetCombatForInstallation(InstallationObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) {
float damage = calculateDamageForInstallation(attacker, target, weapon, command);
if(damage > 0) {
damage *= 1.5f;
int damageBeforeArmor = (int) damage;
damage *= 0.99;
int armorAbsorbed = (int) (damageBeforeArmor - damage);
if(damage > 0)
applyDamageForInstallation(attacker, target, (int) damage);
sendCombatPacketsForInstallation(attacker, target, weapon, command, actionCounter, damage, armorAbsorbed, HitType.CRITICAL);
if(FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName() + ".py"))
core.scriptService.callScript("scripts/commands/combat/", command.getCommandName(), "run", core, attacker, target, damage);
return;
}
}
private void sendCombatPackets(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter, float damage, int armorAbsorbed, int hitType) {
@@ -485,6 +785,21 @@ public class CombatService implements INetworkDispatch {
}
private void sendCombatPacketsForInstallation(InstallationObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter, float damage, int armorAbsorbed, int hitType) {
String animationStr = command.getRandomAnimation(weapon);
int turret_fire = 0xD334C0B8; // 0xA7595B4E
//CombatAction combatAction = new CombatAction(CRC.StringtoCRC(animationStr), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC());
CombatAction combatAction = new CombatAction(turret_fire, attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC());
ObjControllerMessage objController = new ObjControllerMessage(0x1B, combatAction);
attacker.notifyObserversInRange(objController, true, 125);
CombatSpam combatSpam = new CombatSpam(attacker.getObjectID(), target.getObjectID(), weapon.getObjectID(), (int) damage, armorAbsorbed, hitType);
ObjControllerMessage objController4 = new ObjControllerMessage(0x1B, combatSpam);
IoBuffer spam = objController4.serialize();
if(target.getClient() != null)
target.getClient().getSession().write(spam);
}
private void sendHealPackets(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) {
CombatAction combatAction = new CombatAction(CRC.StringtoCRC(command.getDefaultAnimations()[0]), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC());
@@ -682,6 +997,23 @@ public class CombatService implements INetworkDispatch {
return rawDamage;
}
private float calculateDamageForInstallation(InstallationObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command) {
float rawDamage = command.getAddedDamage();
if(command.getPercentFromWeapon() > 0) {
float weaponMinDmg = weapon.getMinDamage();
float weaponMaxDmg = weapon.getMaxDamage();
float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg;
weaponDmg *= command.getPercentFromWeapon();
rawDamage += weaponDmg;
}
return rawDamage;
}
private float calculateDamage(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command) {
@@ -723,6 +1055,24 @@ public class CombatService implements INetworkDispatch {
}
private float calculateDamageForInstallation(InstallationObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command) {
float rawDamage = command.getAddedDamage();
if(command.getPercentFromWeapon() > 0 && weapon != attacker.getSlottedObject("default_weapon")) {
float weaponMinDmg = weapon.getMinDamage();
float weaponMaxDmg = weapon.getMaxDamage();
float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg;
weaponDmg *= command.getPercentFromWeapon();
rawDamage += weaponDmg;
}
return rawDamage;
}
public byte getHitType(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command) {
float r;
@@ -1148,6 +1498,26 @@ public class CombatService implements INetworkDispatch {
core.playerService.sendCloningWindow(target, attacker.getSlottedObject("ghost") != null);
}
public void deathblowPlayerFromInstallation(InstallationObject attacker, CreatureObject target) {
target.stopIncapTask();
target.setIncapTask(null);
target.setPosture(Posture.Dead);
attacker.removeDefender(target);
target.removeDefender(attacker);
target.setSpeedMultiplierBase(0);
target.setTurnRadius(0);
if (attacker.getSlottedObject("ghost") != null)
target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_dead", "TT", attacker.getCustomName()), DisplayType.Broadcast);
else
target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_dead", "TT", "@" + attacker.getStfFilename() + ":" + attacker.getStfName()), DisplayType.Broadcast);
core.playerService.sendCloningWindow(target, attacker.getSlottedObject("ghost") != null);
}
public boolean areInDuel(CreatureObject creature1, CreatureObject creature2) {
if(creature1.getDuelList().contains(creature2) && creature2.getDuelList().contains(creature1))
@@ -1385,7 +1755,7 @@ public class CombatService implements INetworkDispatch {
if(creature.getClient() == null) {
if (creature.getAttachment("AI")!=null){
AIActor aiActor = (AIActor) creature.getAttachment("AI");
CreatureObject target = aiActor.getFollowObject();
TangibleObject target = aiActor.getFollowObject();
if (target.getClient()!=null)
client = target.getClient(); // Use player's client reference that is in combat with that NPC
}