mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-08-02 02:15:48 -04:00
780 lines
22 KiB
Plaintext
780 lines
22 KiB
Plaintext
/***** INCLUDES ********************************************************/
|
|
|
|
include library.ai_lib;
|
|
include library.attrib;
|
|
include library.battlefield;
|
|
include library.combat;
|
|
include library.factions;
|
|
include library.hq;
|
|
include library.list;
|
|
include library.pclib;
|
|
include library.pet_lib;
|
|
include library.player_structure;
|
|
include library.turret;
|
|
include library.utils;
|
|
include library.xp;
|
|
|
|
inherits systems.combat.combat_base_old;
|
|
|
|
/***** TRIGGERS ********************************************************/
|
|
trigger OnAttach()
|
|
{
|
|
turret.activateTurret(self);
|
|
ai_lib.setAttackable(self, true);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
trigger OnInitialize()
|
|
{
|
|
/* Advanced turrets still get this script attached to them, but it is
|
|
detached on initialization. However, this trigger still goes off
|
|
and we don't want them to be blowed up.
|
|
*/
|
|
string template = getTemplateName(self);
|
|
if(template.indexOf("adv") > -1)
|
|
return SCRIPT_CONTINUE;
|
|
|
|
explodeTurret(self, self);
|
|
|
|
|
|
/* LEGACY TURRET, USE ADVANCED_TURRET_AI FROM NOW ON.
|
|
string factionName = factions.getFaction( self );
|
|
if ( factionName != null )
|
|
factions.setFaction( self, factionName );
|
|
|
|
if ( getHitpoints(self) < 1 )
|
|
setHitpoints(self, 1);
|
|
|
|
utils.setScriptVar(self, "ai.level", 100);
|
|
|
|
int tFac = pvpGetAlignedFaction(self);
|
|
setTurretAttributes(self, tFac);
|
|
|
|
setWantSawAttackTriggers( self, true );
|
|
|
|
if( hasObjVar(self, "objWeapon") )
|
|
{
|
|
obj_id wpn = getObjIdObjVar(self, "objWeapon");
|
|
if ( !isIdValid(wpn) )
|
|
{
|
|
removeObjVar(self, "objWeapon");
|
|
turret.createWeapon(self);
|
|
}
|
|
else
|
|
{
|
|
if ( !utils.isNestedWithin(wpn, self) )
|
|
{
|
|
removeObjVar(self, "objWeapon");
|
|
turret.createWeapon(self);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
turret.createWeapon(self);
|
|
}
|
|
|
|
setTurretAttributes(self, tFac);
|
|
*/
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
trigger OnPvpFactionChanged(int oldFaction, int newFaction)
|
|
{
|
|
//debugSpeakMsg(self, "faction updated: "+oldFaction+" -> "+newFaction);
|
|
setTurretAttributes(self, newFaction);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
|
|
void setTurretAttributes(obj_id self, int turretFaction)
|
|
{
|
|
if ( hasTriggerVolume(self, turret.ALERT_VOLUME_NAME) )
|
|
removeTriggerVolume(turret.ALERT_VOLUME_NAME);
|
|
|
|
if ( hasTriggerVolume(self, turret.VOL_TOO_CLOSE) )
|
|
removeTriggerVolume(turret.VOL_TOO_CLOSE);
|
|
|
|
//debugSpeakMsg(self, "clearing interested attribs");
|
|
clearAttributeInterested(self, attrib.ALL);
|
|
clearAttributeInterested(self, attrib.IMPERIAL);
|
|
clearAttributeInterested(self, attrib.REBEL);
|
|
clearAttributeInterested(self, attrib.HUTT);
|
|
|
|
|
|
createTriggerVolume( turret.ALERT_VOLUME_NAME, turret.ALERT_VOLUME_SIZE, true );
|
|
//createTriggerVolume( turret.VOL_TOO_CLOSE, turret.RANGE_TOO_CLOSE, true );
|
|
|
|
//debugSpeakMsg(self, "setting interest attribs for faction: "+newFaction);
|
|
switch ( turretFaction )
|
|
{
|
|
case ##"rebel":
|
|
setAttributeInterested( self, attrib.ALL );
|
|
setAttributeInterested( self, attrib.IMPERIAL );
|
|
setAttributeInterested( self, attrib.HUTT );
|
|
pvpSetAlignedFaction(self, ##"Rebel");
|
|
pvpMakeCovert(self);
|
|
break;
|
|
|
|
case ##"imperial":
|
|
setAttributeInterested( self, attrib.ALL );
|
|
setAttributeInterested( self, attrib.REBEL );
|
|
setAttributeInterested( self, attrib.HUTT );
|
|
pvpSetAlignedFaction(self, ##"Imperial");
|
|
pvpMakeCovert(self);
|
|
break;
|
|
|
|
default:
|
|
setAttributeInterested( self, attrib.ALL );
|
|
break;
|
|
}
|
|
}
|
|
|
|
trigger OnRemovingFromWorld()
|
|
{
|
|
if ( hasObjVar( self, "lair.deadLair" ))
|
|
destroyObject( self );
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
trigger OnAboutToOpenContainer(obj_id who)
|
|
{
|
|
if ( isIdValid(who) && !isGod(who) )
|
|
return SCRIPT_OVERRIDE;
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
trigger OnAboutToLoseItem(obj_id destContainer, obj_id transferer, obj_id item)
|
|
{
|
|
if ( isIdValid(transferer) && !isGod(transferer) )
|
|
return SCRIPT_OVERRIDE;
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
trigger OnAboutToReceiveItem(obj_id srcContainer, obj_id transferer, obj_id item)
|
|
{
|
|
if ( isIdValid(transferer) && !isGod(transferer) )
|
|
return SCRIPT_OVERRIDE;
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
trigger OnTriggerVolumeEntered( string volumeName, obj_id who )
|
|
{
|
|
if (!isIdValid(who))
|
|
return SCRIPT_CONTINUE;
|
|
|
|
int curHP = getHitpoints (self);
|
|
if ( curHP < 1 )
|
|
{
|
|
explodeTurret( self, who);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
if ( !pvpCanAttack(self, who) )
|
|
{
|
|
//debugSpeakMsg(who, "cannot attack this PVP target");
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
//LOG("turret","***** OnVolEntered: self = " + self + " now = " + getGameTime() + " ********");
|
|
//LOG("turret"," - vol = " + volumeName + " who = " + who);
|
|
if ( volumeName.equals( turret.ALERT_VOLUME_NAME ) && who != self )
|
|
{
|
|
//debugSpeakMsg(who, "breached by " + who);
|
|
turret.addTarget(self, who);
|
|
}
|
|
else if ( volumeName.equals( turret.VOL_TOO_CLOSE ) && who != self )
|
|
{
|
|
turret.removeTarget(self, who);
|
|
}
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
trigger OnTriggerVolumeExited( string volumeName, obj_id who )
|
|
{
|
|
//LOG("turret","***** OnVolExited: self = " + self + " now = " + getGameTime() + " ********");
|
|
//LOG("turret"," - vol = " + volumeName + " target = " + who);
|
|
if ( volumeName.equals( turret.ALERT_VOLUME_NAME ) && who != self )
|
|
{
|
|
turret.removeTarget(self, who);
|
|
if (turret.isEngaged(self))
|
|
{
|
|
obj_id target = utils.getObjIdScriptVar(self, turret.SCRIPTVAR_ENGAGED);
|
|
if (target == who)
|
|
{
|
|
turret.disengage(self);
|
|
}
|
|
}
|
|
}
|
|
else if ( volumeName.equals( turret.VOL_TOO_CLOSE ) && who != self )
|
|
{
|
|
turret.addTarget(self, who);
|
|
}
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
trigger OnObjectDamaged(obj_id attacker, obj_id weapon, int damage)
|
|
{
|
|
//LOG("turret","***** OnObjectDamaged: self = " + self + " now = " + getGameTime() + " ********");
|
|
int curHP = getHitpoints (self);
|
|
if ( curHP < 1 )
|
|
{
|
|
explodeTurret( self, attacker );
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
turret.addTarget(self, attacker);
|
|
|
|
if (!utils.hasScriptVar (self, "playingEffect"))
|
|
{
|
|
int smolder = 2000;
|
|
int fire = 1000;
|
|
|
|
if (curHP < smolder)
|
|
{
|
|
if (curHP < fire)
|
|
{
|
|
location death = getLocation (self);
|
|
playClientEffectLoc(attacker, "clienteffect/lair_hvy_damage_fire.cef" , death, 0);
|
|
utils.setScriptVar (self, "playingEffect", 1);
|
|
messageTo (self, "effectManager", null, 15, true);
|
|
}
|
|
else
|
|
{
|
|
location death = getLocation (self);
|
|
playClientEffectLoc(attacker, "clienteffect/lair_med_damage_smoke.cef" , death, 0);
|
|
utils.setScriptVar (self, "playingEffect", 1);
|
|
messageTo (self, "effectManager", null, 15, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
|
|
trigger OnSawAttack(obj_id defender, obj_id[] attackers)
|
|
{
|
|
if ( getConfigSetting("GameServer", "disableAICombat")!=null )
|
|
{
|
|
//LOG("turret","***GameServer:disableAICombat engaged -> setting saw attack to FALSE");
|
|
setWantSawAttackTriggers(self, false);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
int numAtt = attackers.length;
|
|
for ( int i = 0; i < numAtt; i++ )
|
|
{
|
|
obj_id attacker = attackers[i];
|
|
if(pvpCanAttack(self, attacker))
|
|
{
|
|
turret.addTarget(self, attacker);
|
|
}
|
|
}
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
|
|
/***** FUNCTIONS *******************************************************/
|
|
obj_id getGoodTurretTarget()
|
|
{
|
|
//LOG("turret","getGoodTurretTarget: entered...");
|
|
obj_id self = getSelf();
|
|
|
|
if ( !utils.hasScriptVar(self, turret.SCRIPTVAR_TARGETS) )
|
|
{
|
|
//LOG("turret","getGoodTurretTarget: no target list!");
|
|
return null;
|
|
}
|
|
|
|
//remove incapacitated targets:
|
|
obj_id[] old_targets = utils.getObjIdBatchScriptVar(self, turret.SCRIPTVAR_TARGETS);
|
|
if ( (old_targets == null) || (old_targets.length == 0) )
|
|
{
|
|
//LOG("turret","getGoodTurretTarget: invalid target list!");
|
|
utils.removeBatchScriptVar(self, turret.SCRIPTVAR_TARGETS);
|
|
return null;
|
|
}
|
|
|
|
obj_id[] good_targets = cullInvalidTargets(self, old_targets);
|
|
|
|
//LOG("turret","getGoodTurretTarget: removing incap targets...");
|
|
obj_id[] targets = removeIncapacitatedTargets( self, old_targets );
|
|
|
|
//if all my targets are incapacitated or dead or out of range:
|
|
if ( targets.length == 0 )
|
|
{
|
|
//LOG("turret","getGoodTurretTarget: all targets are incap'd!!");
|
|
|
|
//reload the list of targets:
|
|
targets = good_targets;
|
|
//find an incapacitated one and kill him:
|
|
for ( int i = 0; i < targets.length; i++ )
|
|
{
|
|
if ( isIncapacitated( targets[i] ) && !isDead( targets[i] ) && getDistance(self, targets[i]) <= turret.FACTION_TURRET_RANGE && !pet_lib.isPet(targets[i]))
|
|
{
|
|
//doAttack(targets[i]);
|
|
//LOG("turret","* KILLING TARGET: " + targets[i]);
|
|
pclib.coupDeGrace(targets[i], self);
|
|
//turret.removeTarget( self, targets[i] );
|
|
//return null;
|
|
}
|
|
}
|
|
|
|
//they must all be dead or out of range:
|
|
//utils.removeScriptVar(self, turret.SCRIPTVAR_ENGAGED);
|
|
//utils.removeBatchScriptVar(self, turret.SCRIPTVAR_TARGETS);
|
|
return obj_id.NULL_ID;
|
|
}
|
|
|
|
if ( utils.hasScriptVar(self, xp.VAR_ATTACKER_LIST) )
|
|
{
|
|
resizeable obj_id[] attackerList = utils.getResizeableObjIdBatchScriptVar(self, xp.VAR_ATTACKER_LIST);
|
|
if ( attackerList != null && attackerList.length > 0 )
|
|
{
|
|
obj_var[] ovs = new obj_var[attackerList.length];
|
|
for ( int i = 0; i < attackerList.length; i++ )
|
|
{
|
|
string scriptVarPath = xp.VAR_ATTACKER_LIST + "." + attackerList[i] + ".damage";
|
|
ovs[i] = new obj_var(attackerList.elementAt(i).toString(), utils.getIntScriptVar(self, scriptVarPath));
|
|
}
|
|
|
|
ovs = list.quickSort(0, ovs.length-1, ovs);
|
|
if ( (ovs != null) && (ovs.length > 0) )
|
|
{
|
|
for ( int i = 0; i < ovs.length; i++ )
|
|
{
|
|
string ovName = ovs[i].getName();
|
|
obj_id tmp = utils.stringToObjId(ovName);
|
|
if ( isIdValid(tmp) )
|
|
{
|
|
if ( utils.getElementPositionInArray(targets, tmp) > -1 )
|
|
{
|
|
//LOG("turret","getGoodTurretTarget: returning tracked damage target = " + tmp);
|
|
if ( canSee(self, tmp) )
|
|
return tmp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//LOG("turret","getGoodTurretTarget: unable to sort damage tracking array for valid target...");
|
|
|
|
//pick one at random:
|
|
int idx = rand(0,targets.length-1);
|
|
//LOG("turret","getGoodTurretTarget: returning random (" + idx + ") target = " + targets[idx]);
|
|
if ( !turret.isValidTarget(self, targets[idx]) )
|
|
{
|
|
turret.removeTarget(self, targets[idx]);
|
|
return self;
|
|
}
|
|
|
|
return targets[idx];
|
|
}
|
|
|
|
obj_id[] cullInvalidTargets(obj_id self, obj_id[] old_targets)
|
|
{
|
|
if ( old_targets == null || old_targets.length == 0 )
|
|
return null;
|
|
|
|
resizeable obj_id[] toRemove = new obj_id[0];
|
|
for ( int i = 0; i < old_targets.length; i++ )
|
|
{
|
|
if ( !turret.isValidTarget(self, old_targets[i]) || getDistance(self, old_targets[i]) > turret.FACTION_TURRET_RANGE )
|
|
toRemove = utils.addElement(toRemove, old_targets[i]);
|
|
}
|
|
|
|
if ( toRemove != null && toRemove.length > 0 )
|
|
{
|
|
resizeable obj_id[] targets = new Vector(Arrays.asList(old_targets));
|
|
targets = utils.removeElements(targets, toRemove);
|
|
return targets;
|
|
}
|
|
|
|
return old_targets;
|
|
}
|
|
|
|
//return a list of targets that are neither dead nor incapacitated nor out of range:
|
|
obj_id[] removeIncapacitatedTargets( obj_id self, obj_id[] targets )
|
|
{
|
|
if ( !isIdValid(self) || (targets == null) || (targets.length == 0) )
|
|
return null;
|
|
|
|
resizeable obj_id[] newTargets = new obj_id[0];
|
|
for ( int i = 0; i < targets.length; i++ )
|
|
{
|
|
if (!ai_lib.isAiDead(targets[i]) && getDistance(self, targets[i]) <= turret.FACTION_TURRET_RANGE )
|
|
newTargets = utils.addElement( newTargets, targets[i] );
|
|
}
|
|
|
|
return newTargets;
|
|
}
|
|
|
|
void explodeTurret( obj_id turretid, obj_id killer )
|
|
{
|
|
obj_id base = getObjIdObjVar(turretid, hq.VAR_DEFENSE_PARENT);
|
|
obj_id[] enemies = getWhoIsTargetingMe( turretid );
|
|
if ( enemies != null )
|
|
{
|
|
for ( int i = 0; i < enemies.length; i++ )
|
|
{
|
|
queueClearCommandsFromGroup(enemies[i], ##"combat_general");
|
|
queueClearCommandsFromGroup(enemies[i], ##"combat_melee");
|
|
queueClearCommandsFromGroup(enemies[i], ##"combat_ranged");
|
|
setTarget( enemies[i], null );
|
|
}
|
|
}
|
|
|
|
location death = getLocation(turretid);
|
|
playClientEffectLoc(killer, "clienteffect/combat_explosion_lair_large.cef", death, 0);
|
|
|
|
if ( hasObjVar(turretid, player_structure.VAR_PLAYER_STRUCTURE) )
|
|
{
|
|
turret.deactivateTurret(turretid);
|
|
player_structure.destroyStructure(turretid, false);
|
|
}
|
|
else
|
|
{
|
|
turret.deactivateTurret(turretid);
|
|
hq.validateDefenseTracking(base);
|
|
messageTo(turretid, "handleDestroyTurret", null, 2, false);
|
|
}
|
|
|
|
hq.validateDefenseTracking(base);
|
|
messageTo(turretid, "handleDestroyTurret", null, 10f, false);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief performs an attach from the turret to the target
|
|
*
|
|
* @return void
|
|
***********************************************************************/
|
|
float doAttack()
|
|
{
|
|
//LOG("turret","*** doAttack(): entered...");
|
|
obj_id self = getSelf();
|
|
obj_id base = getObjIdObjVar(self, hq.VAR_DEFENSE_PARENT);
|
|
|
|
if ( !turret.isActive(self) )
|
|
{
|
|
return -1.0f;
|
|
}
|
|
|
|
int curHP = getHitpoints (self);
|
|
if ( curHP < 1 )
|
|
{
|
|
hq.validateDefenseTracking(base);
|
|
messageTo(self, "handleDestroyTurret", null, 2, false);
|
|
return -1.0f;
|
|
}
|
|
|
|
|
|
obj_id target = utils.getObjIdScriptVar(self, turret.SCRIPTVAR_ENGAGED);
|
|
if ( !isIdValid(target) || !target.isLoaded() || (ai_lib.isAiDead(target)) || !canSee(self, target) )
|
|
{
|
|
obj_id tmptarget = getGoodTurretTarget();
|
|
//LOG("turret","doAttack:returned getGoodTurretTarget = " + target);
|
|
if ( tmptarget == null )
|
|
{
|
|
//LOG("turret","doAttack: unable to locate a valid target... sleeping...");
|
|
return -2.0f;
|
|
}
|
|
else if ( tmptarget == obj_id.NULL_ID ) //can't find a valid non-incap target
|
|
{
|
|
if (utils.hasScriptVar(self,"NULL_ID Counter"))
|
|
{
|
|
if(utils.getIntScriptVar(self,"NULL_ID Counter") > 5) //if we've already tried a bit, abort the loops
|
|
{
|
|
return -2.0f; //I dunno why -2.0f. I'm just mimicing what was done int he block directly above. Probably a personal debug value used by RPalacio back in the day.
|
|
}
|
|
else
|
|
{
|
|
int searchLoopCounter = utils.getIntScriptVar(self,"NULL_ID Counter");
|
|
utils.setScriptVar(self,"NULL_ID Counter", ++searchLoopCounter);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
utils.setScriptVar(self,"NULL_ID Counter",1) ;
|
|
}
|
|
//("turret","doAttack: unable to locate a valid NON-INCAP target... waiting...");
|
|
return 5.0f;
|
|
}
|
|
else if ( tmptarget == self )
|
|
{
|
|
//LOG("turret","Broke! This should probably be a NEGATIVE delay.");
|
|
return 1f;
|
|
}
|
|
else if ( tmptarget == target )
|
|
{
|
|
return 5.0f;
|
|
}
|
|
|
|
target = tmptarget;
|
|
turret.engageTarget(self, target);
|
|
}
|
|
|
|
return doAttack(target);
|
|
}
|
|
|
|
float doAttack(obj_id target)
|
|
{
|
|
//LOG("turret","*** doAttack(target): entered...");
|
|
obj_id self = getSelf();
|
|
obj_id base = getObjIdObjVar(self, hq.VAR_DEFENSE_PARENT);
|
|
|
|
if ( !isIdValid(self) || !isIdValid(target) )
|
|
{
|
|
//LOG("turret","doAttack(target): invalid params!!");
|
|
return -1.0f;
|
|
}
|
|
|
|
int curHP = getHitpoints (self);
|
|
if ( curHP < 1 )
|
|
{
|
|
hq.validateDefenseTracking(base);
|
|
messageTo(self, "handleDestroyTurret", null, 2, false);
|
|
return -1.0f;
|
|
}
|
|
|
|
//waitasec (or 5) - if we have no weapon yet.
|
|
if(!hasObjVar(self, "objWeapon"))
|
|
{
|
|
//LOG("turret","doAttack(target): unable to locate weapon objvar!!");
|
|
return -1.0f;
|
|
}
|
|
|
|
if ( !canSee(self, target) )
|
|
{
|
|
//LOG("turret","doAttack(target): turret(" + self + ") unable see target(" + target + ")!!");
|
|
obj_id tmptarget = getGoodTurretTarget();
|
|
if ( isIdValid(tmptarget) && tmptarget != target )
|
|
{
|
|
target = tmptarget;
|
|
turret.engageTarget(self, target);
|
|
}
|
|
else
|
|
{
|
|
return 2.0f;
|
|
}
|
|
}
|
|
|
|
if ( !turret.isValidTarget(self, target) )
|
|
{
|
|
//LOG("turret","doAttack(target): turret(" + self + ") targetting invalid target(" + target + ")!!");
|
|
turret.removeTarget(self, target);
|
|
return 2.0f;
|
|
}
|
|
|
|
messageTo(self, "reconfirmTarget", null, 5, false);
|
|
|
|
const float DAMAGE_MODIFIER = 2.0f; // modifier for damage from basic attack
|
|
// attrib cost mods
|
|
const float HEALTH_COST_MODIFIER = 0;;
|
|
const float ACTION_COST_MODIFIER = 0;
|
|
|
|
const int BASE_TO_HIT_MODIFIER = 0; // how far off of 75 do we want the base to hit roll
|
|
const float AMMO_COST_MODIFIER = 1.0f; // modifier for ammo cost
|
|
|
|
string[] strTimeMods = {""};
|
|
string[] strDamageMods = {""};
|
|
string[] strCostMods = {};
|
|
string[] strToHitMods= {""};
|
|
|
|
string[] strBlockMods = {""};
|
|
string[] strEvadeMods = {""};
|
|
string[] strCounterAttackMods = {""};
|
|
|
|
// special response information
|
|
int intBlockMod = 1000; //The larger number makes it more difficult to block
|
|
int intEvadeMod = 1000; //The larger number makes it more difficult to evade
|
|
int intCounterAttackMod = 1000; //The larger number makes it more difficult to counter
|
|
|
|
int intAttackerEndPosture = POSTURE_NONE;
|
|
int intDefenderEndPosture = POSTURE_NONE; // DON'T MIX THESE UP!
|
|
|
|
string strPlaybackAction = "fire_turret";
|
|
|
|
int[] intEffects = {
|
|
}; // const int's defined in base_class
|
|
float[] fltEffectDurations = {
|
|
};
|
|
int intChanceToApplyEffect= 0; // 1-100 rating for whether we apply a state
|
|
|
|
obj_id objWeapon = getObjIdObjVar(self, "objWeapon");
|
|
//LOG("combat_spam", "weapon is "+objWeapon);
|
|
|
|
attacker_data cbtAttackerData = new attacker_data();
|
|
weapon_data cbtWeaponData = new weapon_data();
|
|
obj_id[] objDefenders = new obj_id[1];
|
|
objDefenders[0] = target;
|
|
|
|
defender_data[] cbtDefenderData = new defender_data[objDefenders.length]; // ALWAYS AN ARRAY DO NOT EVER CHANGE DO NOT NEVER!
|
|
if (!getCombatData(self, objDefenders, cbtAttackerData, cbtDefenderData, cbtWeaponData))
|
|
{
|
|
//LOG("Combat", "WARNING: turret_ai.doAttack call to getCombatData returned false");
|
|
return -1.0f;
|
|
}
|
|
|
|
// begin giant hack!
|
|
//LOG("turret_spam", "objWeapon is "+objWeapon);
|
|
cbtWeaponData = getWeaponData(objWeapon);
|
|
|
|
hit_result[] cbtHitData = new hit_result[1];
|
|
cbtHitData[0] = calculateHit(cbtAttackerData, cbtDefenderData[0], cbtWeaponData);
|
|
|
|
//LOG("combat_spam","Got hit engine results!");
|
|
|
|
attacker_results cbtAttackerResults = new attacker_results(); // blank data for attacker information
|
|
cbtAttackerResults.id = self; // MUST DO THIS!
|
|
|
|
defender_results[] cbtDefenderResults = new defender_results[1];
|
|
cbtDefenderResults[0] = new defender_results();
|
|
|
|
// pass by reference below, so be careful
|
|
//LOG("combat_spam","Setting Combat Results!");
|
|
//setDefenderCombatResults(cbtAttackerData, cbtAttackerResults, cbtHitData, cbtDefenderData, cbtDefenderResults, strBlockMods, intBlockMod, strEvadeMods, intEvadeMod, strCounterAttackMods, intCounterAttackMod, true); // sorry this function sucks so much
|
|
cbtAttackerResults.endPosture = -1;
|
|
debugServerConsoleMsg(self, "posture set");
|
|
cbtAttackerResults.weapon = objWeapon;
|
|
debugServerConsoleMsg(self, "weapon");
|
|
//LOG("combat_spam", "My target is now "+target);
|
|
cbtDefenderResults[0].id = target;
|
|
debugServerConsoleMsg(self, "target");
|
|
cbtDefenderResults[0].endPosture = getPosture(target);
|
|
debugServerConsoleMsg(self, "defender posture");
|
|
if(cbtHitData[0].success)
|
|
{
|
|
|
|
cbtDefenderResults[0].result = COMBAT_RESULT_HIT;
|
|
}
|
|
else
|
|
{
|
|
|
|
cbtDefenderResults[0].result = COMBAT_RESULT_MISS;
|
|
}
|
|
|
|
debugServerConsoleMsg(self, "hitdata");
|
|
|
|
//LOG("combat_spam","Applying Postures!");
|
|
//applyPostures(cbtAttackerData, cbtAttackerResults, cbtHitData, cbtDefenderData, cbtDefenderResults, intAttackerEndPosture, intDefenderEndPosture, cbtWeaponData);
|
|
|
|
//LOG("combat_spam","Applying States");
|
|
// because these are negative states, we'll alter our list and just pick one..
|
|
|
|
//applyStates(cbtDefenderData, cbtHitData, intChanceToApplyEffect, intEffects, fltEffectDurations); // applies states
|
|
|
|
//LOG("combat_spam","Finalizing Damage");
|
|
|
|
finalizeDamage(cbtAttackerData.id, cbtWeaponData, cbtDefenderData, cbtHitData, cbtDefenderResults, null); // applies all of the necessary damage
|
|
|
|
//LOG("combat_spam","doing combat results!");
|
|
|
|
//LOG("combat_spam","Attacker final posture before docombatresults is "+cbtAttackerResults.endPosture);
|
|
|
|
|
|
string[] strPlaybackNames = makePlaybackNames("fire_turret", cbtHitData, cbtWeaponData, cbtDefenderResults);
|
|
|
|
doCombatResults(strPlaybackNames[0], cbtAttackerResults, cbtDefenderResults);
|
|
|
|
combat.doBasicCombatSpam("shoot", cbtAttackerResults, cbtDefenderResults, cbtHitData);
|
|
|
|
return cbtWeaponData.attackSpeed+rand(0,2);
|
|
}
|
|
|
|
|
|
|
|
/***** MESSAGEHANDLERS *************************************************/
|
|
messageHandler handleTurretAttack()
|
|
{
|
|
//LOG("turret","turret attack reqested...");
|
|
if (utils.hasScriptVar(self,"messageToSerialNum"))
|
|
{
|
|
int storedSerialNumber = utils.getIntScriptVar(self,"messageToSerialNum");
|
|
int sentSerialNumber = params.getInt("messageToSerialNum");
|
|
if (storedSerialNumber != sentSerialNumber)
|
|
{
|
|
//LOG("turret","handleTurretAttack entry: got a different messageTo than the one we were waiting for...ABORTING THIS MESSAGEHANDLER");
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
if ( !turret.isActive(self) )
|
|
{
|
|
//LOG("turret","turret inactive: ignoring turret attack request...");
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
float delay = doAttack();
|
|
//LOG("turret","turret attack: returned delay(" + getGameTime() + ") = " + delay);
|
|
if ( delay > 0f )
|
|
{
|
|
int serialNumber = (int) rand(0,100);
|
|
params.put("messageToSerialNum", serialNumber);
|
|
utils.setScriptVar(self,"messageToSerialNum",serialNumber);
|
|
messageTo( self, "handleTurretAttack", params, delay, false );
|
|
}
|
|
else
|
|
{
|
|
utils.removeScriptVar(self, turret.SCRIPTVAR_ENGAGED);
|
|
utils.removeScriptVar(self, "messageToSerialNum");
|
|
utils.removeScriptVar( self, "ai.combat.isInCombat");
|
|
}
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
|
|
/*This message handler is just the delay for the client effects. It makes
|
|
sure that multiple effects aren't playing at the same time and eating up
|
|
the frame rate. */
|
|
messageHandler effectManager ()
|
|
{
|
|
utils.removeScriptVar (self, "playingEffect");
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
messageHandler expireLair()
|
|
{
|
|
destroyObject( self );
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
messageHandler enemyDecloaked()
|
|
{
|
|
//LOG("turret","enemy decloaked entered...");
|
|
if ( (params == null) || (params.isEmpty()) )
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
obj_id target = params.getObjId("target");
|
|
//LOG("turret","decloaked enemy target = " + target + " " + getEncodedName(target));
|
|
if ( isIdValid(target) )
|
|
{
|
|
if ( getDistance(self, target) <= turret.FACTION_TURRET_RANGE )
|
|
{
|
|
turret.addTarget(self, target);
|
|
}
|
|
}
|
|
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
messageHandler handleDestroyTurret()
|
|
{
|
|
destroyObject(self);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
|
|
|
|
|