mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-07-13 22:01:04 -04:00
342 lines
13 KiB
Java
Executable File
342 lines
13 KiB
Java
Executable File
package script.ai;
|
|
|
|
import script.deltadictionary;
|
|
import script.library.utils;
|
|
import script.location;
|
|
import script.obj_id;
|
|
|
|
public class ai_combat_movement extends script.base_script
|
|
{
|
|
public ai_combat_movement()
|
|
{
|
|
}
|
|
public static final int MOVEMODE_INVALID = 0;
|
|
public static final int MOVEMODE_FOLLOW = 1;
|
|
public static final int MOVEMODE_RANDOM = 2;
|
|
public static final int MOVEMODE_PREPARING_TO_MOVE = 3;
|
|
public static final int MOVEMODE_PATHING_HOME = 4;
|
|
public static final int MOVEMODE_PREPARING_TO_STAND = 5;
|
|
public static final int MOVEMODE_MOVING_TO_HEAL = 7;
|
|
public static final int MOVEMODE_IDLE = 9;
|
|
public static final int MOVEMODE_FLEE = 10;
|
|
public static final int MOVEMODE_FOLLOW_FORMATION = 11;
|
|
public static final int MOVEMODE_MOVING_TO_SEE = 12;
|
|
public static final int MOVEMODE_MOVING_TO_DEATHBLOW = 13;
|
|
public static final int MOVEMODE_SWARM = 14;
|
|
public static final int MOVEMOVE_EVADE = 15;
|
|
public static void aiClearMoveMode() throws InterruptedException
|
|
{
|
|
final obj_id self = getSelf();
|
|
deltadictionary dict = self.getScriptVars();
|
|
dict.put("ai.combat.moveMode", MOVEMODE_INVALID);
|
|
}
|
|
public static void aiIdle() throws InterruptedException
|
|
{
|
|
if (aiIsIdle())
|
|
{
|
|
return;
|
|
}
|
|
final obj_id self = getSelf();
|
|
if (aiGetMovementState(self) == MOVEMENT_PATROL && !hasSuspendedMovement(self))
|
|
{
|
|
suspendMovement(self);
|
|
}
|
|
deltadictionary dict = self.getScriptVars();
|
|
dict.put("ai.combat.moveMode", MOVEMODE_IDLE);
|
|
stop(self);
|
|
}
|
|
public static boolean aiIsIdle() throws InterruptedException
|
|
{
|
|
final obj_id self = getSelf();
|
|
final deltadictionary dict = self.getScriptVars();
|
|
return (dict.getInt("ai.combat.moveMode") == MOVEMODE_IDLE);
|
|
}
|
|
public static void aiMoveToSee(obj_id target) throws InterruptedException
|
|
{
|
|
if (aiIsMovingToSee(target))
|
|
{
|
|
return;
|
|
}
|
|
final obj_id self = getSelf();
|
|
if (aiGetMovementState(self) == MOVEMENT_PATROL && !hasSuspendedMovement(self))
|
|
{
|
|
suspendMovement(self);
|
|
}
|
|
deltadictionary dict = self.getScriptVars();
|
|
dict.put("ai.combat.moveMode", MOVEMODE_MOVING_TO_SEE);
|
|
dict.put("ai.combat.moveToSee.target", target);
|
|
pathTo(self, getLocation(target));
|
|
}
|
|
public static boolean aiIsMovingToSee(obj_id target) throws InterruptedException
|
|
{
|
|
if (aiIsMovingToSee() && aiGetMoveToSeeTarget() == target)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public static boolean aiIsMovingToSee() throws InterruptedException
|
|
{
|
|
final obj_id self = getSelf();
|
|
final deltadictionary dict = self.getScriptVars();
|
|
return (dict.getInt("ai.combat.moveMode") == MOVEMODE_MOVING_TO_SEE);
|
|
}
|
|
public static obj_id aiGetMoveToSeeTarget() throws InterruptedException
|
|
{
|
|
final obj_id self = getSelf();
|
|
final deltadictionary dict = self.getScriptVars();
|
|
return dict.getObjId("ai.combat.moveToSee.target");
|
|
}
|
|
public static void aiMoveToDeathBlow(obj_id target) throws InterruptedException
|
|
{
|
|
if (aiIsMovingToDeathBlow(target) || !isIncapacitated(target))
|
|
{
|
|
return;
|
|
}
|
|
final obj_id self = getSelf();
|
|
if (aiGetMovementState(self) == MOVEMENT_PATROL && !hasSuspendedMovement(self))
|
|
{
|
|
suspendMovement(self);
|
|
}
|
|
LOGC(aiLoggingEnabled(self) && !isIncapacitated(target), "debug_ai", "ai_combat_movement::aiMoveToDeathBlow() self(" + self + ":" + getName(self) + ") target(" + target + ") Trying to death blow a non-incapacitated target.");
|
|
deltadictionary dict = self.getScriptVars();
|
|
dict.put("ai.combat.moveMode", MOVEMODE_MOVING_TO_DEATHBLOW);
|
|
dict.put("ai.combat.moveToDeathBlow.target", target);
|
|
pathTo(self, getLocation(target));
|
|
}
|
|
public static boolean aiIsMovingToDeathBlow(obj_id target) throws InterruptedException
|
|
{
|
|
if ((aiIsMovingToDeathBlow()) && (aiGetMoveToDeathBlowTarget() == target))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public static boolean aiIsMovingToDeathBlow() throws InterruptedException
|
|
{
|
|
final obj_id self = getSelf();
|
|
final deltadictionary dict = self.getScriptVars();
|
|
return (dict.getInt("ai.combat.moveMode") == MOVEMODE_MOVING_TO_DEATHBLOW);
|
|
}
|
|
public static obj_id aiGetMoveToDeathBlowTarget() throws InterruptedException
|
|
{
|
|
final obj_id self = getSelf();
|
|
final deltadictionary dict = self.getScriptVars();
|
|
return dict.getObjId("ai.combat.moveToDeathBlow.target");
|
|
}
|
|
public static void aiFollow(obj_id target, float minDistance, float maxDistance) throws InterruptedException
|
|
{
|
|
if (aiIsFollowing(target, minDistance, maxDistance))
|
|
{
|
|
return;
|
|
}
|
|
final obj_id self = getSelf();
|
|
if (aiGetMovementState(self) == MOVEMENT_PATROL && !hasSuspendedMovement(self))
|
|
{
|
|
suspendMovement(self);
|
|
}
|
|
deltadictionary dict = self.getScriptVars();
|
|
dict.put("ai.combat.moveMode", MOVEMODE_FOLLOW);
|
|
dict.put("ai.combat.follow.target", target);
|
|
dict.put("ai.combat.follow.minDistance", minDistance);
|
|
dict.put("ai.combat.follow.maxDistance", maxDistance);
|
|
follow(self, target, minDistance, maxDistance);
|
|
}
|
|
public static void aiSwarm(obj_id target, float minDistance, float maxDistance) throws InterruptedException
|
|
{
|
|
if (aiIsSwarming(target, minDistance, maxDistance))
|
|
{
|
|
return;
|
|
}
|
|
final obj_id self = getSelf();
|
|
if (aiGetMovementState(self) == MOVEMENT_PATROL && !hasSuspendedMovement(self))
|
|
{
|
|
suspendMovement(self);
|
|
}
|
|
deltadictionary dict = self.getScriptVars();
|
|
dict.put("ai.combat.moveMode", MOVEMODE_SWARM);
|
|
dict.put("ai.combat.follow.target", target);
|
|
dict.put("ai.combat.follow.minDistance", minDistance);
|
|
dict.put("ai.combat.follow.maxDistance", maxDistance);
|
|
swarm(self, target);
|
|
}
|
|
public static boolean aiIsFollowing(obj_id target, float minDistance, float maxDistance) throws InterruptedException
|
|
{
|
|
final obj_id self = getSelf();
|
|
final deltadictionary dict = self.getScriptVars();
|
|
if ((dict.getInt("ai.combat.moveMode") == MOVEMODE_FOLLOW) && (dict.getObjId("ai.combat.follow.target") == target) && (dict.getFloat("ai.combat.follow.minDistance") == minDistance) && (dict.getFloat("ai.combat.follow.maxDistance") == maxDistance))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public static boolean aiIsSwarming(obj_id target, float minDistance, float maxDistance) throws InterruptedException
|
|
{
|
|
final obj_id self = getSelf();
|
|
final deltadictionary dict = self.getScriptVars();
|
|
if ((dict.getInt("ai.combat.moveMode") == MOVEMODE_SWARM) && (dict.getObjId("ai.combat.follow.target") == target) && (dict.getFloat("ai.combat.follow.minDistance") == minDistance) && (dict.getFloat("ai.combat.follow.maxDistance") == maxDistance))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public static float getActualEvadeChance(obj_id ai, float min, float max) throws InterruptedException
|
|
{
|
|
float rslt = max;
|
|
float difference = max - min;
|
|
float maxHealth = (float)getMaxHealth(ai);
|
|
float curHealth = (float)getHealth(ai);
|
|
rslt -= (difference * (curHealth / maxHealth));
|
|
return rslt;
|
|
}
|
|
public static boolean aiEvade(obj_id target, obj_id ai, range_info aiWeaponRanges, float minChance, float maxChance) throws InterruptedException
|
|
{
|
|
obj_id primaryWeapon = aiGetPrimaryWeapon(ai);
|
|
obj_id secondaryWeapon = aiGetSecondaryWeapon(ai);
|
|
float primaryRange = 0;
|
|
float secondaryRange = 0;
|
|
obj_id master = getMaster(ai);
|
|
if (isIdValid(master))
|
|
{
|
|
return false;
|
|
}
|
|
if (hasScript(ai, "systems.dungeon_sequencer.ai_controller"))
|
|
{
|
|
return false;
|
|
}
|
|
if (isIdValid(primaryWeapon) && exists(primaryWeapon))
|
|
{
|
|
final range_info primaryWeaponRange = aiGetWeaponRangeInfo(primaryWeapon);
|
|
primaryRange = primaryWeaponRange.maxRange;
|
|
}
|
|
if (isIdValid(secondaryWeapon) && exists(secondaryWeapon))
|
|
{
|
|
final range_info secondaryWeaponRange = aiGetWeaponRangeInfo(secondaryWeapon);
|
|
secondaryRange = secondaryWeaponRange.maxRange;
|
|
}
|
|
if (primaryRange <= 10f && secondaryRange <= 10f)
|
|
{
|
|
return false;
|
|
}
|
|
final int now = getGameTime();
|
|
final int then = utils.getIntScriptVar(ai, "aiIsEvading");
|
|
if (then != 0 && (now - then) < 15)
|
|
{
|
|
return false;
|
|
}
|
|
float minDistance = 0;
|
|
float maxDistance = 1f;
|
|
if (getTopMostContainer(ai) == ai)
|
|
{
|
|
minDistance = 15f;
|
|
maxDistance = 20f;
|
|
}
|
|
else
|
|
{
|
|
minDistance = 4f;
|
|
maxDistance = 10f;
|
|
}
|
|
if (isPlayer(target))
|
|
{
|
|
float mod = 0;
|
|
range_info playerRange = getWeaponRangeInfo(getCurrentWeapon(target));
|
|
if (playerRange != null && playerRange.maxRange < 10)
|
|
{
|
|
if (minChance == 1f)
|
|
{
|
|
mod = 0.985f;
|
|
}
|
|
else
|
|
{
|
|
mod = 0.9f;
|
|
}
|
|
minDistance = 5f;
|
|
if (rand(1, 100) < 30)
|
|
{
|
|
maxDistance = playerRange.maxRange + 5;
|
|
}
|
|
else
|
|
{
|
|
maxDistance = playerRange.maxRange - 1;
|
|
}
|
|
if (minDistance > maxDistance)
|
|
{
|
|
minDistance = maxDistance;
|
|
}
|
|
}
|
|
maxChance -= (maxChance * mod);
|
|
if (minChance > maxChance)
|
|
{
|
|
minChance = maxChance;
|
|
}
|
|
}
|
|
float chance = getActualEvadeChance(ai, minChance, maxChance);
|
|
if (chance < 1f && rand(0.0f, 1.0f) > chance)
|
|
{
|
|
return false;
|
|
}
|
|
location evasionTargetLoc = getValidAwayLocation(target, minDistance, maxDistance);
|
|
if (evasionTargetLoc == null || getLocation(ai).cell != evasionTargetLoc.cell)
|
|
{
|
|
return false;
|
|
}
|
|
if (!canSee(ai, evasionTargetLoc))
|
|
{
|
|
return false;
|
|
}
|
|
utils.setScriptVar(ai, "aiIsEvading", getGameTime());
|
|
pathTo(ai, evasionTargetLoc);
|
|
faceTo(ai, target);
|
|
return true;
|
|
}
|
|
public static location getValidAwayLocation(obj_id mob, float minDistance, float maxDistance) throws InterruptedException
|
|
{
|
|
location from = getLocation(mob);
|
|
location evasionTarget = utils.getRandomAwayLocation(from, minDistance, maxDistance);
|
|
evasionTarget.y += 0.5f;
|
|
if (!canSee(mob, evasionTarget))
|
|
{
|
|
return null;
|
|
}
|
|
evasionTarget.y -= 0.5f;
|
|
return evasionTarget;
|
|
}
|
|
public static void aiFlee(obj_id target, float distance) throws InterruptedException
|
|
{
|
|
if (aiIsFleeing(target, distance))
|
|
{
|
|
return;
|
|
}
|
|
final obj_id self = getSelf();
|
|
if (aiGetMovementState(self) == MOVEMENT_PATROL && !hasSuspendedMovement(self))
|
|
{
|
|
suspendMovement(self);
|
|
}
|
|
deltadictionary dict = self.getScriptVars();
|
|
dict.put("ai.combat.moveMode", MOVEMODE_FLEE);
|
|
dict.put("ai.combat.flee.target", target);
|
|
dict.put("ai.combat.flee.distance", distance);
|
|
flee(self, target, distance, distance);
|
|
messageTo(self, "redoYaw", null, 30, false);
|
|
}
|
|
public static boolean aiIsFleeing(obj_id ai) throws InterruptedException
|
|
{
|
|
final deltadictionary dict = ai.getScriptVars();
|
|
return dict.getInt("ai.combat.moveMode") == MOVEMODE_FLEE;
|
|
}
|
|
public static boolean aiIsFleeing(obj_id target, float distance) throws InterruptedException
|
|
{
|
|
final obj_id self = getSelf();
|
|
final deltadictionary dict = self.getScriptVars();
|
|
if ((dict.getInt("ai.combat.moveMode") == MOVEMODE_FLEE) && (dict.getObjId("ai.combat.flee.target") == target) && (dict.getFloat("ai.combat.flee.distance") == distance))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public static boolean isAiImmobile(obj_id subject) throws InterruptedException
|
|
{
|
|
return hasObjVar(subject, "isImmobile") ? getBooleanObjVar(subject, "isImmobile") : false;
|
|
}
|
|
}
|