mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-07-31 00:15:54 -04:00
480 lines
12 KiB
Plaintext
480 lines
12 KiB
Plaintext
/**
|
|
* Title: turret.scriptlib
|
|
* Description: function library for supplemental turret ai and functionality
|
|
*/
|
|
|
|
/***** INCLUDES ********************************************************/
|
|
|
|
include library.utils;
|
|
include library.factions;
|
|
include library.battlefield;
|
|
|
|
/***** CONSTANTS *******************************************************/
|
|
|
|
const string ALERT_VOLUME_NAME = "alertTriggerVolume";
|
|
const float ALERT_VOLUME_SIZE = 120.0f;
|
|
const float FACTION_TURRET_RANGE = 96.0f;
|
|
const float TURRET_RANGE = 80.0f;
|
|
|
|
const string VOL_TOO_CLOSE = "volTooClose";
|
|
const float RANGE_TOO_CLOSE = 10f;
|
|
|
|
const string VAR_TURRET_BASE = "turret";
|
|
|
|
const string VAR_IS_ACTIVE = VAR_TURRET_BASE + ".isActive";
|
|
const string VAR_IS_GENERIC = VAR_TURRET_BASE + ".isGeneric";
|
|
const string SCRIPTVAR_ENGAGED = VAR_TURRET_BASE + ".engaged";
|
|
const string SCRIPTVAR_TARGETS = VAR_TURRET_BASE + ".targetList";
|
|
|
|
const string OBJVAR_CAN_ATTACK = "turret.validTargetObjVar"; // this is the objvar the turret will look for on the target to see
|
|
// if the target is valid - generic turrets only
|
|
const string OBJVAR_TURRET_FRIEND = "turret.isFriend"; // friends never get attacked
|
|
|
|
|
|
/***** FUNCTIONS *******************************************************/
|
|
/***********************************************************************
|
|
* @brief sets a turrets status to active
|
|
*
|
|
* @return void
|
|
***********************************************************************/
|
|
void activateTurret( obj_id turret )
|
|
{
|
|
if ( !isIdValid(turret) )
|
|
return;
|
|
|
|
if( !hasObjVar(turret, "objWeapon") )
|
|
if ( !createWeapon(turret) )
|
|
return;
|
|
|
|
setObjVar(turret, VAR_IS_ACTIVE, true);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief sets a turrets status to active
|
|
*
|
|
* @return void
|
|
***********************************************************************/
|
|
void deactivateTurret( obj_id turret )
|
|
{
|
|
if ( !isIdValid(turret) )
|
|
return;
|
|
|
|
removeObjVar(turret, VAR_IS_ACTIVE);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief determines if a turret is active
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean isActive( obj_id turret )
|
|
{
|
|
if ( !isIdValid(turret) )
|
|
return false;
|
|
|
|
if ( hasObjVar(turret, VAR_IS_ACTIVE) )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief sets a turrets status to active
|
|
*
|
|
* @return void
|
|
***********************************************************************/
|
|
void engageTarget(obj_id turret, obj_id target)
|
|
{
|
|
if ( !isIdValid(turret) || !isIdValid(target) )
|
|
return;
|
|
|
|
if ( !isActive(turret) )
|
|
return;//already active
|
|
|
|
utils.setScriptVar( turret, "ai.combat.isInCombat", true );
|
|
utils.setScriptVar(turret, SCRIPTVAR_ENGAGED, target);
|
|
setCombatTarget(turret, target);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief sets a turrets status to active
|
|
*
|
|
* @return void
|
|
***********************************************************************/
|
|
void disengage( obj_id turret )
|
|
{
|
|
if ( !isIdValid(turret) )
|
|
return;
|
|
utils.removeScriptVar( turret, "ai.combat.isInCombat");
|
|
utils.removeScriptVar(turret, SCRIPTVAR_ENGAGED);
|
|
setCombatTarget(turret, null);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief determines if a turret is active
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean isEngaged( obj_id turret )
|
|
{
|
|
if ( !isIdValid(turret) )
|
|
return false;
|
|
|
|
if (utils.hasScriptVar( turret, "ai.combat.isInCombat"))
|
|
return true;
|
|
|
|
if ( utils.hasScriptVar(turret, SCRIPTVAR_ENGAGED) )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief attempts to create a weapon object for the turret
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean createWeapon( obj_id turret )
|
|
{
|
|
//LOG("turret","createWeapon: entered...");
|
|
if ( !isIdValid(turret) )
|
|
return false;
|
|
|
|
if( hasObjVar(turret, "objWeapon") )
|
|
return false; // already initialized. !
|
|
|
|
string strWeaponTemplate;
|
|
if( hasObjVar(turret, "strWeaponTemplate") )
|
|
strWeaponTemplate = getStringObjVar(turret, "strWeaponTemplate");
|
|
else
|
|
strWeaponTemplate = "object/weapon/ranged/turret/turret_block_large.iff";
|
|
|
|
obj_id objWeapon = createObject(strWeaponTemplate, turret, "");
|
|
if( !isIdValid(objWeapon) )
|
|
{
|
|
//LOG("combat_spam", "NULL WEAPON");
|
|
//LOG("turret","createWeapon: null weapon...");
|
|
return false;
|
|
}
|
|
|
|
//LOG("combat_spam", "objWeapon is "+objWeapon);
|
|
//LOG("turret", "objWeapon is "+objWeapon);
|
|
return setObjVar(turret, "objWeapon", objWeapon);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief identifies if the target is a valid turret target on a GENERIC turret
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean isValidTargetGeneric(obj_id turret, obj_id target)
|
|
{
|
|
if ( !isIdValid(turret) || !isIdValid(target) )
|
|
return false;
|
|
|
|
if ( target == turret )
|
|
return false;
|
|
|
|
location there = getLocation(target);
|
|
location here = getLocation(turret);
|
|
if ( !isIdValid(here.cell))
|
|
{
|
|
//I am outdoors:
|
|
if ( there == null || isIdValid(there.cell) )
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//I am indoors:
|
|
if ( there.cell != here.cell )
|
|
return false;//we're in different cells
|
|
}
|
|
|
|
float dist = getDistance(getLocation(turret), getLocation(target));
|
|
if ( dist > TURRET_RANGE + 1)
|
|
{
|
|
//debugSpeakMsg(target, "target is out of range " + dist);
|
|
return false;
|
|
}
|
|
|
|
return canGenericTurretAttackTarget(target);
|
|
}
|
|
|
|
//
|
|
// checks to see if this turret is set up as a generic turret
|
|
//
|
|
boolean isGenericTurret(obj_id turret)
|
|
{
|
|
return hasObjVar(turret, VAR_IS_GENERIC);
|
|
}
|
|
|
|
//
|
|
// check the target of a generic turret against the presenc of an objvar
|
|
//
|
|
boolean canGenericTurretAttackTarget(obj_id target)
|
|
{
|
|
if(!isIdValid(target) || !exists(target))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(hasObjVar(target, OBJVAR_TURRET_FRIEND))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
obj_id self = getSelf();
|
|
|
|
if(!hasObjVar(self, OBJVAR_CAN_ATTACK))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string objvar = getStringObjVar(self, OBJVAR_CAN_ATTACK);
|
|
if(hasObjVar(target, objvar) || objvar.equals("all") || (objvar.equals("allPlayers") && isPlayer(target)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* @brief identifies if the target is a valid turret target
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean isValidTarget(obj_id turret, obj_id target)
|
|
{
|
|
if ( !isIdValid(turret) || !isIdValid(target) )
|
|
return false;
|
|
|
|
if ( target == turret )
|
|
return false;
|
|
|
|
location there = getLocation(target);
|
|
location here = getLocation(turret);
|
|
if ( !isIdValid(here.cell))
|
|
{
|
|
//I am outdoors:
|
|
if ( there == null || isIdValid(there.cell) )
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//I am indoors:
|
|
if ( there.cell != here.cell )
|
|
return false;//we're in different cells
|
|
}
|
|
|
|
region btlField = battlefield.getBattlefield(turret);
|
|
if ( btlField != null )
|
|
{
|
|
if ( pvpIsEnemy(turret, target) )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
float dist = getDistance(getLocation(turret), getLocation(target));
|
|
if ( dist > TURRET_RANGE + 1)
|
|
{
|
|
//debugSpeakMsg(target, "target is out of range " + dist);
|
|
return false;
|
|
}
|
|
|
|
/* commented out so that default pvp rules determine target validity
|
|
if ( isPlayer(target) )
|
|
{
|
|
boolean canAttack = pvpCanAttack(turret, target);
|
|
//LOG("turret","turret(" + turret + ") vs target(" + target + "): pvpCanAttack = " + canAttack);
|
|
return canAttack;
|
|
}
|
|
else
|
|
{
|
|
string myFaction = factions.getFaction( turret );
|
|
if ( myFaction == null )
|
|
{
|
|
myFaction = factions.getFactionNameByHashCode( pvpGetAlignedFaction( turret ) );
|
|
}
|
|
|
|
string yourFaction = factions.getFaction( target );
|
|
if ( yourFaction == null )
|
|
{
|
|
yourFaction = factions.getFactionNameByHashCode( pvpGetAlignedFaction( target ) );
|
|
}
|
|
|
|
//LOG("turret","turret faction = " + myFaction + " target faction = " + yourFaction);
|
|
if ( myFaction == null || yourFaction == null )
|
|
return false;
|
|
|
|
if ( factions.areFactionsOpposed(myFaction, yourFaction) )
|
|
return true;
|
|
}
|
|
*/
|
|
|
|
//replaces above
|
|
|
|
if ( isPlayer(target) )
|
|
{
|
|
//debugSpeakMsg(target, "target is player");
|
|
return pvpCanAttack(turret, target);
|
|
}
|
|
else
|
|
{
|
|
//debugSpeakMsg(target, "target is not a player");
|
|
return pvpIsEnemy(turret, target);
|
|
}
|
|
|
|
//return false;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief adds a valid target to the target list
|
|
*
|
|
* @return void
|
|
***********************************************************************/
|
|
void addTarget(obj_id turret, obj_id target)
|
|
{
|
|
//LOG("turret","addTarget: entered...");
|
|
if ( !isIdValid(turret) || !isIdValid(target) )
|
|
{
|
|
//LOG("turret","addTarget: invalid params");
|
|
//debugSpeakMsg(target, "I am invalid");
|
|
return;
|
|
}
|
|
|
|
if ( target == turret )
|
|
return;
|
|
|
|
if(!isGenericTurret(turret))
|
|
{
|
|
if ( !isValidTarget(turret, target) )
|
|
{
|
|
//debugSpeakMsg(target, "turret thinks I am invalid");
|
|
//LOG("turret","addTarget: not a valid target!");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!isValidTargetGeneric(turret, target))
|
|
{
|
|
//LOG("turret", "addTarget: not a valid target for generic turret");
|
|
return;
|
|
}
|
|
}
|
|
|
|
float dist = getDistance(getLocation(turret), getLocation(target));
|
|
if ( dist > TURRET_RANGE + 1 /*|| dist < RANGE_TOO_CLOSE*/ )
|
|
{
|
|
//debugSpeakMsg(target, "I am out of range");
|
|
//LOG("turret","addTarget: target not within valid range!");
|
|
return;
|
|
}
|
|
|
|
if ( !utils.hasScriptVar(turret, SCRIPTVAR_TARGETS) )
|
|
{
|
|
resizeable obj_id[] targets = utils.addElement(null, target);
|
|
//LOG("turret","addTarget: attempting to set targets scriptvar");
|
|
utils.setBatchScriptVar(turret, SCRIPTVAR_TARGETS, targets);
|
|
//debugSpeakMsg(target, "adding me to targets list");
|
|
}
|
|
else
|
|
{
|
|
resizeable obj_id[] targets = utils.getResizeableObjIdBatchScriptVar(turret, SCRIPTVAR_TARGETS);
|
|
if ( targets != null && targets.length > 0 )
|
|
{
|
|
if ( !utils.isElementInArray(targets, target) )
|
|
{
|
|
targets = utils.addElement(targets, target);
|
|
//LOG("turret","addTarget: attempting to set targets scriptvar");
|
|
utils.setBatchScriptVar(turret, SCRIPTVAR_TARGETS, targets);
|
|
//LOG("turret","addTarget: targets scriptvar set!");
|
|
//debugSpeakMsg(target, "adding me to the targets list");
|
|
}
|
|
}
|
|
}
|
|
|
|
////LOG("turret","addTarget: fall-thru...");
|
|
if ( !isEngaged(turret) )
|
|
{
|
|
utils.setScriptVar( turret, "ai.combat.isInCombat", true);
|
|
messageTo(turret, "handleTurretAttack", null, 1, false);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief adds a valid target to the target list
|
|
*
|
|
* @return void
|
|
***********************************************************************/
|
|
void addTargets(obj_id turret, obj_id[] target)
|
|
{
|
|
if ( !isIdValid(turret) || (target == null) || (target.length == 0) )
|
|
return;
|
|
|
|
resizeable obj_id[] targets = utils.getResizeableObjIdBatchScriptVar(turret, SCRIPTVAR_TARGETS);
|
|
for ( int i = 0; i < target.length; i++ )
|
|
{
|
|
if ( isValidTarget(turret, target[i]) && !utils.isElementInArray(targets, target) )
|
|
{
|
|
targets = utils.addElement(targets, target[i]);
|
|
}
|
|
}
|
|
|
|
if ( (targets != null) && (targets.length > 0) )
|
|
{
|
|
utils.setBatchScriptVar(turret, SCRIPTVAR_TARGETS, targets);
|
|
}
|
|
|
|
if ( !isEngaged(turret) )
|
|
{
|
|
utils.setScriptVar( turret, "ai.combat.isInCombat", true);
|
|
messageTo(turret, "handleTurretAttack", null, 1, false);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief removes a target from the valid target list
|
|
*
|
|
* @return void
|
|
***********************************************************************/
|
|
void removeTarget(obj_id turret, obj_id target)
|
|
{
|
|
if ( !isIdValid(turret) || !isIdValid(target) )
|
|
return;
|
|
|
|
if ( !utils.hasScriptVar(turret, SCRIPTVAR_TARGETS) )
|
|
return;
|
|
|
|
resizeable obj_id[] targets = utils.getResizeableObjIdBatchScriptVar(turret, SCRIPTVAR_TARGETS);
|
|
if ( (targets == null) || (targets.length == 0) )
|
|
return;
|
|
|
|
obj_id engageTarget = utils.getObjIdScriptVar(turret, SCRIPTVAR_ENGAGED);
|
|
|
|
int idx = utils.getElementPositionInArray(targets, target);
|
|
if ( idx > -1 )
|
|
{
|
|
if ( isIdValid(engageTarget) )
|
|
{
|
|
if ( target == engageTarget )
|
|
{
|
|
disengage(turret);
|
|
}
|
|
}
|
|
|
|
targets = utils.removeElementAt(targets, idx);
|
|
if ( (targets == null) || (targets.length == 0) )
|
|
{
|
|
utils.removeBatchScriptVar(turret, SCRIPTVAR_TARGETS);
|
|
return;
|
|
}
|
|
|
|
utils.setBatchScriptVar(turret, SCRIPTVAR_TARGETS, targets);
|
|
}
|
|
}
|
|
|