mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-01-17 00:05:07 -05:00
1199 lines
44 KiB
Java
Executable File
1199 lines
44 KiB
Java
Executable File
package script.ai;
|
|
|
|
import script.*;
|
|
import script.library.*;
|
|
|
|
public class beast extends script.base_script
|
|
{
|
|
public beast()
|
|
{
|
|
}
|
|
public static final String MENU_FILE = "pet/pet_menu";
|
|
public static final int MAX_UNACKNOWLEDGED_MESSAGE_COUNT = 3;
|
|
public static final int PING_INTERVAL = 120;
|
|
public static final int PING_INTERVAL_RETRY = 30;
|
|
public static final float MAX_DISTANCE_FROM_MASTER = 128.0f;
|
|
public static final boolean BEAST_DEBUG = false;
|
|
public static final string_id PCOLOR = new string_id("sui", "set_primary_color");
|
|
public void blog(String text) throws InterruptedException
|
|
{
|
|
if (BEAST_DEBUG)
|
|
{
|
|
LOG("beast.script", text);
|
|
}
|
|
}
|
|
public int OnAttach(obj_id self) throws InterruptedException
|
|
{
|
|
setObjVar(self, "beast.pingMessageNumber", 0);
|
|
setObjVar(self, "beast.lastAcknowledgeNumber", 0);
|
|
messageTo(self, "handleSetupBeast", null, 1, false);
|
|
messageTo(self, "beastPing", null, 5, false);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnAddedToWorld(obj_id self) throws InterruptedException
|
|
{
|
|
messageTo(self, "handleSetupBeast", null, 1, false);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnGetAttributes(obj_id self, obj_id player, String[] names, String[] attribs) throws InterruptedException
|
|
{
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
int idx = utils.getValidAttributeIndex(names);
|
|
obj_id master = getMaster(self);
|
|
obj_id beastBCD = beast_lib.getBeastBCD(self);
|
|
if (!beast_lib.isValidPlayer(master))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
names[idx] = "owner";
|
|
attribs[idx] = getName(master);
|
|
idx++;
|
|
if (exists(beastBCD) && hasObjVar(beastBCD, beast_lib.OBJVAR_BEAST_ENGINEER))
|
|
{
|
|
String creatorName = getStringObjVar(beastBCD, beast_lib.OBJVAR_BEAST_ENGINEER);
|
|
names[idx] = "bm_creator";
|
|
attribs[idx] = creatorName;
|
|
idx++;
|
|
if (idx >= names.length)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
names[idx] = "health";
|
|
attribs[idx] = " " + (int)getMaxAttrib(self, HEALTH);
|
|
idx++;
|
|
int level = getLevel(self);
|
|
if (level < 90)
|
|
{
|
|
dictionary beastStatsNextLevel = utils.dataTableGetRow(beast_lib.BEASTS_STATS, level - 1);
|
|
int experienceLastLevel = 0;
|
|
int experienceNextLevel = 0;
|
|
if (level > 1)
|
|
{
|
|
dictionary beastStatsLastLevel = utils.dataTableGetRow(beast_lib.BEASTS_STATS, level - 2);
|
|
if (beastStatsLastLevel == null || beastStatsLastLevel.size() <= 0)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
experienceLastLevel = beastStatsLastLevel.getInt("XP");
|
|
}
|
|
if (beastStatsNextLevel == null || beastStatsNextLevel.size() <= 0)
|
|
{
|
|
blog("initializeBeastStats() missing entry in the " + beast_lib.BEASTS_STATS + " table for level: " + level + ".");
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
experienceNextLevel = beastStatsNextLevel.getInt("XP");
|
|
int beastExperience = beast_lib.getBeastExperience(self);
|
|
int experienceProgress = beastExperience - experienceLastLevel;
|
|
int experienceNeeded = experienceNextLevel - experienceLastLevel;
|
|
int experiencePercentage = 0;
|
|
if (experienceProgress > 0)
|
|
{
|
|
experiencePercentage = (int)(((float)experienceProgress / experienceNeeded) * 100);
|
|
}
|
|
names[idx] = "level_progress";
|
|
attribs[idx] = String.valueOf(experiencePercentage) + "%";
|
|
idx++;
|
|
}
|
|
if (beast_lib.getBeastCanLevel(self))
|
|
{
|
|
names[idx] = "exp_on";
|
|
attribs[idx] = "true";
|
|
idx++;
|
|
}
|
|
else
|
|
{
|
|
names[idx] = "exp_off";
|
|
attribs[idx] = "true";
|
|
idx++;
|
|
}
|
|
names[idx] = beast_lib.BEAST_MOOD_TITLE;
|
|
String currentHappiness = utils.packStringId(beast_lib.convertHappinessString(beastBCD));
|
|
if (currentHappiness != null)
|
|
{
|
|
attribs[idx] = String.valueOf(currentHappiness);
|
|
idx++;
|
|
if (idx >= names.length)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
names[idx] = beast_lib.BEAST_LOYALTY_TITLE;
|
|
String currentLoyalty = utils.packStringId(beast_lib.convertLoyaltyString(beastBCD));
|
|
if (currentLoyalty != null)
|
|
{
|
|
attribs[idx] = String.valueOf(currentLoyalty);
|
|
idx++;
|
|
if (idx >= names.length)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
int loyaltyPercentage = beast_lib.getBeastLoyaltyToNextLevelPercentage(self);
|
|
if (loyaltyPercentage >= 0)
|
|
{
|
|
names[idx] = beast_lib.BEAST_LOYALTY_PERCENTAGE_TITLE;
|
|
attribs[idx] = String.valueOf(loyaltyPercentage) + "%";
|
|
idx++;
|
|
if (idx >= names.length)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
String[] abilityList = beast_lib.getBeastmasterPetBarData(player, self);
|
|
int slotsAvalable = getSkillStatisticModifier(player, "expertise_bm_add_pet_bar");
|
|
if (!abilityList[3].equals("") && slotsAvalable >= 0 && !abilityList[3].equals("empty") && !abilityList[3].equals("disabled"))
|
|
{
|
|
names[idx] = "bm_ability_1";
|
|
attribs[idx] = String.valueOf(utils.packStringId(new string_id("cmd_n", abilityList[3])));
|
|
idx++;
|
|
}
|
|
if (!abilityList[4].equals("") && slotsAvalable >= 1 && !abilityList[4].equals("empty") && !abilityList[4].equals("disabled"))
|
|
{
|
|
names[idx] = "bm_ability_2";
|
|
attribs[idx] = String.valueOf(utils.packStringId(new string_id("cmd_n", abilityList[4])));
|
|
idx++;
|
|
}
|
|
if (!abilityList[5].equals("") && slotsAvalable >= 2 && !abilityList[5].equals("empty") && !abilityList[5].equals("disabled"))
|
|
{
|
|
names[idx] = "bm_ability_3";
|
|
attribs[idx] = String.valueOf(utils.packStringId(new string_id("cmd_n", abilityList[5])));
|
|
idx++;
|
|
}
|
|
if (!abilityList[6].equals("") && slotsAvalable >= 3 && !abilityList[6].equals("empty") && !abilityList[6].equals("disabled"))
|
|
{
|
|
names[idx] = "bm_ability_4";
|
|
attribs[idx] = String.valueOf(utils.packStringId(new string_id("cmd_n", abilityList[6])));
|
|
idx++;
|
|
}
|
|
names[idx] = "armorhpmax";
|
|
attribs[idx] = String.valueOf((utils.getIntScriptVar(self, "beast.display.armor") + getEnhancedSkillStatisticModifier(self, "private_armor_bonus")));
|
|
idx++;
|
|
obj_id beastWeapon = getCurrentWeapon(self);
|
|
if (isIdValid(beastWeapon))
|
|
{
|
|
int minDamage = getWeaponMinDamage(beastWeapon);
|
|
int maxDamage = getWeaponMaxDamage(beastWeapon);
|
|
int expertiseDamageBonus = getEnhancedSkillStatisticModifierUncapped(self, "expertise_damage_all");
|
|
minDamage = (int)(minDamage * (1.0f + (expertiseDamageBonus / 100.0f)));
|
|
maxDamage = (int)(maxDamage * (1.0f + (expertiseDamageBonus / 100.0f)));
|
|
float weaponSpeed = getWeaponAttackSpeed(beastWeapon);
|
|
names[idx] = "damage";
|
|
attribs[idx] = minDamage + " - " + maxDamage;
|
|
idx++;
|
|
names[idx] = "attackspeed";
|
|
attribs[idx] = String.valueOf(weaponSpeed);
|
|
idx++;
|
|
float beastDPS = utils.roundFloatByDecimal((minDamage + maxDamage) / weaponSpeed / 2);
|
|
names[idx] = "basedps";
|
|
attribs[idx] = String.valueOf(beastDPS);
|
|
idx++;
|
|
}
|
|
else
|
|
{
|
|
obj_id defaultWeapon = getDefaultWeapon(self);
|
|
if (isIdValid(defaultWeapon))
|
|
{
|
|
int minDamage = getWeaponMinDamage(defaultWeapon);
|
|
int maxDamage = getWeaponMaxDamage(defaultWeapon);
|
|
float weaponSpeed = getWeaponAttackSpeed(defaultWeapon);
|
|
int expertiseDamageBonus = getEnhancedSkillStatisticModifierUncapped(self, "expertise_damage_all");
|
|
minDamage = (int)(minDamage * (1.0f + (expertiseDamageBonus / 100.0f)));
|
|
maxDamage = (int)(maxDamage * (1.0f + (expertiseDamageBonus / 100.0f)));
|
|
names[idx] = "damage";
|
|
attribs[idx] = minDamage + " - " + maxDamage;
|
|
idx++;
|
|
names[idx] = "attackspeed";
|
|
attribs[idx] = String.valueOf(weaponSpeed);
|
|
idx++;
|
|
float beastDPS = utils.roundFloatByDecimal((minDamage + maxDamage) / weaponSpeed / 2);
|
|
names[idx] = "basedps";
|
|
attribs[idx] = String.valueOf(beastDPS);
|
|
idx++;
|
|
}
|
|
}
|
|
if (beast_lib.DISPLAY_NAMES.length == beast_lib.ARRAY_BEAST_INCUBATION_STATS.length && beast_lib.DISPLAY_NAMES.length == beast_lib.DISPLAY_CONVERSION_RATES.length)
|
|
{
|
|
for (int i = 0; i < beast_lib.DISPLAY_NAMES.length; ++i)
|
|
{
|
|
String name = beast_lib.DISPLAY_NAMES[i];
|
|
if (!name.contains("_skill"))
|
|
{
|
|
if (!name.equals("block_value_bonus"))
|
|
{
|
|
names[idx] = beast_lib.DISPLAY_NAMES[i];
|
|
attribs[idx] = String.valueOf(utils.roundFloatByDecimal((utils.getFloatScriptVar(self, beast_lib.ARRAY_BEAST_INCUBATION_STATS[i]) * beast_lib.DISPLAY_CONVERSION_RATES[i]))) + "%";
|
|
idx++;
|
|
}
|
|
else
|
|
{
|
|
names[idx] = beast_lib.DISPLAY_NAMES[i];
|
|
attribs[idx] = String.valueOf(utils.roundFloatByDecimal(utils.getFloatScriptVar(self, beast_lib.ARRAY_BEAST_INCUBATION_STATS[i])));
|
|
idx++;
|
|
}
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
names[idx] = beast_lib.DISPLAY_NAMES[i];
|
|
attribs[idx] = String.valueOf(utils.roundFloatByDecimal(utils.getFloatScriptVar(self, beast_lib.ARRAY_BEAST_INCUBATION_STATS[i])));
|
|
idx++;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
float glanceReduct = beast_lib.getBeastModGlancingReduction(self);
|
|
if (glanceReduct > 0)
|
|
{
|
|
names[idx] = "bm_glance_reduct";
|
|
attribs[idx] = String.valueOf(glanceReduct) + "%";
|
|
idx++;
|
|
if (idx >= names.length)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
float damageReduct = beast_lib.getBeastModDamageReduction(self);
|
|
if (damageReduct > 0)
|
|
{
|
|
names[idx] = "bm_damage_reduct";
|
|
attribs[idx] = String.valueOf(damageReduct) + "%";
|
|
idx++;
|
|
if (idx >= names.length)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
float punishReduct = beast_lib.getBeastModPunishingReduction(self);
|
|
if (punishReduct > 0)
|
|
{
|
|
names[idx] = "bm_punish_reduct";
|
|
attribs[idx] = String.valueOf(punishReduct) + "%";
|
|
idx++;
|
|
if (idx >= names.length)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnDetach(obj_id self) throws InterruptedException
|
|
{
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id master = getMaster(self);
|
|
if (isIdValid(master))
|
|
{
|
|
if (isIdValid(beast_lib.getBeastOnPlayer(master)))
|
|
{
|
|
blog("Beast not cleaned up on " + master + " and something attempted to detach its beast script.");
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnDestroy(obj_id self) throws InterruptedException
|
|
{
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id master = getMaster(self);
|
|
if (isIdValid(master))
|
|
{
|
|
if (isIdValid(beast_lib.getBeastOnPlayer(master)))
|
|
{
|
|
blog("Beast not cleaned up on " + master + " and something attempted to destroy it.");
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handleSetupBeast(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id master = getMaster(self);
|
|
if (!isIdValid(master) || !exists(master))
|
|
{
|
|
blog("handleSetupBeast() master is not valid. Destroying beast.");
|
|
destroyObject(self);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (isPlayer(master))
|
|
{
|
|
setObjVar(self, "ai.pet", true);
|
|
}
|
|
beast_lib.beastFollowTarget(self, master);
|
|
if (!ai_lib.isInCombat(self) && stealth.canBeastStealth(self))
|
|
{
|
|
stealth.makeBeastInvisible(master, "appearance/pt_smoke_puff.prt");
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int beastPing(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
int lastMessage = getIntObjVar(self, "beast.pingMessageNumber");
|
|
int nextMessage = lastMessage + 1;
|
|
setObjVar(self, "beast.pingMessageNumber", nextMessage);
|
|
int acknowledgedMessage = getIntObjVar(self, "beast.lastAcknowledgeNumber");
|
|
int unacknowledgedGap = lastMessage - acknowledgedMessage;
|
|
obj_id master = getMaster(self);
|
|
if (!isIdValid(master) || !exists(master))
|
|
{
|
|
setMaster(self, null);
|
|
blog("beastPing() master is not valid. Destroying beast.");
|
|
if (destroyObject(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
else
|
|
{
|
|
blog("beastPing() failed to destroy the beast with no master online");
|
|
}
|
|
}
|
|
obj_id bcd = beast_lib.getBeastBCD(self);
|
|
if (!beast_lib.isValidBCD(bcd))
|
|
{
|
|
setMaster(self, null);
|
|
blog("beastPing() bcd is not valid. Destroying beast.");
|
|
if (destroyObject(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
else
|
|
{
|
|
blog("beastPing() failed to destroy the beast with no BCD online");
|
|
}
|
|
}
|
|
if (unacknowledgedGap > MAX_UNACKNOWLEDGED_MESSAGE_COUNT)
|
|
{
|
|
beast_lib.storeBeast(bcd);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (getDistance(self, master) > MAX_DISTANCE_FROM_MASTER)
|
|
{
|
|
blog("self: " + self + " too far from master: " + master + "(" + getDistance(self, master) + " and is being stored.");
|
|
beast_lib.storeBeast(bcd);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
int nextCallbackInterval = (unacknowledgedGap <= 0) ? PING_INTERVAL : PING_INTERVAL_RETRY;
|
|
dictionary messageData = new dictionary();
|
|
messageData.put("beastId", self);
|
|
messageData.put("messageId", nextMessage);
|
|
messageTo(bcd, "beastPing", messageData, 1, false);
|
|
messageTo(self, "beastPing", null, nextCallbackInterval, false);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int bcdPingResponse(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
int ack = params.getInt("messageId");
|
|
int previousAck = getIntObjVar(self, "beast.pingMessageNumber");
|
|
if (ack > previousAck)
|
|
{
|
|
setObjVar(self, "beast.lastAcknowledgeNumber", ack);
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int resumeDefaultCalmBehavior(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id master = getMaster(self);
|
|
if (!isIdValid(master))
|
|
{
|
|
blog("resumeDefaultCalmBehavior() master is invalid and is being destroyed.");
|
|
destroyObject(self);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (ai_lib.isInCombat(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (isIdValid(master))
|
|
{
|
|
location masterLoc = getLocation(master);
|
|
if(isValidLocation(masterLoc))
|
|
setHomeLocation(self, masterLoc);
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int checkMovementSpeed(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
obj_id target = params.getObjId("target");
|
|
beast_lib.validateFollowTarget(self, target);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnFollowWaiting(obj_id self, obj_id target) throws InterruptedException
|
|
{
|
|
beast_lib.validateFollowTarget(self, target);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnFollowMoving(obj_id self, obj_id target) throws InterruptedException
|
|
{
|
|
beast_lib.validateFollowTarget(self, target);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnBehaviorChange(obj_id self, int newBehavior, int oldBehavior, int[] changeFlags) throws InterruptedException
|
|
{
|
|
if (ai_lib.isAiDead(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (ai_lib.isInCombat(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
LOG("beast", "OnBehaviorChange newBehavior: " + newBehavior + " oldBehavior: " + oldBehavior);
|
|
if (newBehavior <= oldBehavior)
|
|
{
|
|
if (doCalmerBehavior(self, newBehavior, oldBehavior) == SCRIPT_CONTINUE)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
else
|
|
{
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (doAgitatedBehavior(self, newBehavior, oldBehavior) == SCRIPT_CONTINUE)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
else
|
|
{
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
}
|
|
}
|
|
public int doCalmerBehavior(obj_id npc, int newBehavior, int oldBehavior) throws InterruptedException
|
|
{
|
|
switch (newBehavior)
|
|
{
|
|
case BEHAVIOR_CALM:
|
|
break;
|
|
case BEHAVIOR_ALERT:
|
|
break;
|
|
case BEHAVIOR_THREATEN:
|
|
break;
|
|
case BEHAVIOR_FLEE:
|
|
break;
|
|
case BEHAVIOR_PANIC:
|
|
break;
|
|
case BEHAVIOR_ATTACK:
|
|
break;
|
|
case BEHAVIOR_FRENZY:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
public int doAgitatedBehavior(obj_id npc, int newBehavior, int oldBehavior) throws InterruptedException
|
|
{
|
|
switch (newBehavior)
|
|
{
|
|
case BEHAVIOR_CALM:
|
|
break;
|
|
case BEHAVIOR_ALERT:
|
|
break;
|
|
case BEHAVIOR_THREATEN:
|
|
break;
|
|
case BEHAVIOR_FLEE:
|
|
break;
|
|
case BEHAVIOR_PANIC:
|
|
break;
|
|
case BEHAVIOR_ATTACK:
|
|
break;
|
|
case BEHAVIOR_FRENZY:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
public int lairThreatened(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
public int OnIncapacitated(obj_id self, obj_id attacker) throws InterruptedException
|
|
{
|
|
beast_lib.killBeast(self, attacker);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handleBeastIncappedDecay(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
int incapTimer = utils.getIntScriptVar(self, "incapTimer");
|
|
int messageTimer = params.getInt("incapTimer");
|
|
if (incapTimer != messageTimer)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id master = getMaster(self);
|
|
if (!isIdValid(master))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (isIncapacitated(self))
|
|
{
|
|
blog("handleBeastIncappedDecay() destroying self from incapacitation.");
|
|
destroyObject(self);
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnRecapacitated(obj_id self) throws InterruptedException
|
|
{
|
|
beast_lib.beastFollowTarget(self, getMaster(self));
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnObjectMenuRequest(obj_id self, obj_id player, menu_info mi) throws InterruptedException
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (isDead(self) || ai_lib.aiIsDead(player))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (player != getMaster(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (ai_lib.isInCombat(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
int opt_menu = 0;
|
|
if (beast_lib.isBeastMaster(player))
|
|
{
|
|
if (!beast_lib.getBeastCanLevel(self))
|
|
{
|
|
mi.addRootMenu(menu_info_types.SERVER_MENU1, new string_id(MENU_FILE, "exp_on"));
|
|
}
|
|
else
|
|
{
|
|
mi.addRootMenu(menu_info_types.SERVER_MENU1, new string_id(MENU_FILE, "exp_off"));
|
|
}
|
|
}
|
|
obj_id bcd = beast_lib.getBeastBCD(self);
|
|
if (!ai_lib.isInCombat(player) && !ai_lib.isAiDead(self) && !ai_lib.aiIsDead(player))
|
|
{
|
|
mi.addRootMenu(menu_info_types.SERVER_MENU2, new string_id("beast", "name_beast"));
|
|
}
|
|
if (!ai_lib.isInCombat(player))
|
|
{
|
|
mi.addRootMenu(menu_info_types.PET_STORE, new string_id(MENU_FILE, "menu_store"));
|
|
}
|
|
if (ai_lib.isAiDead(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (hasObjVar(bcd, beast_lib.OBJVAR_OLD_PET_IDENTIFIER) && !hasObjVar(bcd, beast_lib.OBJVAR_OLD_PET_REHUED))
|
|
{
|
|
mi.addRootMenu(menu_info_types.SERVER_MENU3, PCOLOR);
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnObjectMenuSelect(obj_id self, obj_id player, int item) throws InterruptedException
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (ai_lib.aiIsDead(player))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (ai_lib.isInCombat(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (player != getMaster(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id bcd = beast_lib.getBeastBCD(self);
|
|
if (!isIdValid(bcd) || !exists(bcd))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (ai_lib.isAiDead(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (ai_lib.isInCombat(player) || ai_lib.isAiDead(player))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (item == menu_info_types.SERVER_MENU1)
|
|
{
|
|
boolean canLevel = !beast_lib.getBeastCanLevel(self);
|
|
beast_lib.setBeastCanLevel(self, canLevel);
|
|
beast_lib.setBCDBeastCanLevel(bcd, canLevel);
|
|
sendDirtyObjectMenuNotification(self);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (item == menu_info_types.SERVER_MENU2)
|
|
{
|
|
if (!ai_lib.isInCombat(player) && !ai_lib.isAiDead(self) && !ai_lib.aiIsDead(player))
|
|
{
|
|
sui.inputbox(self, player, "@beast:name_d", sui.OK_CANCEL, "@beast:name_t", sui.INPUT_NORMAL, null, "handleSetBeastName", null);
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (item == menu_info_types.PET_STORE)
|
|
{
|
|
if (callable.hasCallable(player, callable.CALLABLE_TYPE_COMBAT_PET))
|
|
{
|
|
obj_id currentBeast = callable.getCallable(player, callable.CALLABLE_TYPE_COMBAT_PET);
|
|
if (ai_lib.isInCombat(currentBeast))
|
|
{
|
|
sendSystemMessage(player, new string_id("beast", "beast_cant_store"));
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
beast_lib.storeBeast(bcd);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (item == menu_info_types.PET_COMMAND)
|
|
{
|
|
pet_lib.openLearnCommandSui(self, player);
|
|
}
|
|
if (item == menu_info_types.SERVER_MENU3)
|
|
{
|
|
if (hasObjVar(bcd, beast_lib.OBJVAR_OLD_PET_IDENTIFIER) && !hasObjVar(bcd, beast_lib.OBJVAR_OLD_PET_REHUED))
|
|
{
|
|
sui.colorize(self, player, self, hue.INDEX_1, "handlePrimaryColorize");
|
|
}
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handlePrimaryColorize(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
obj_id beast = self;
|
|
if (!isValidId(beast))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id bcd = beast_lib.getBeastBCD(beast);
|
|
if (!isValidId(bcd))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
int idx = sui.getColorPickerIndex(params);
|
|
int bp = sui.getIntButtonPressed(params);
|
|
if (bp == sui.BP_CANCEL)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (idx > -1)
|
|
{
|
|
setObjVar(bcd, beast_lib.OBJVAR_BEAST_HUE, idx);
|
|
hue.setColor(beast, "/private/index_color_1", idx);
|
|
setObjVar(bcd, beast_lib.OBJVAR_OLD_PET_REHUED, 1);
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handleSetBeastName(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
obj_id player = sui.getPlayerId(params);
|
|
String beastName = sui.getInputBoxText(params);
|
|
int btn = sui.getIntButtonPressed(params);
|
|
if (btn == sui.BP_CANCEL)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (beastName.equals("") || isNameReserved(beastName))
|
|
{
|
|
sendSystemMessage(player, new string_id("player_structure", "obscene"));
|
|
sui.inputbox(self, player, "@beast:name_d", sui.OK_CANCEL, "@beast:name_t", sui.INPUT_NORMAL, null, "handleSetBeastName", null);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
beastName = beastName.trim();
|
|
if (beastName.length() < 3)
|
|
{
|
|
sendSystemMessage(player, new string_id("beast", "name_too_short"));
|
|
sui.inputbox(self, player, "@beast:name_d", sui.OK_CANCEL, "@beast:name_t", sui.INPUT_NORMAL, null, "handleSetBeastName", null);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (beastName.length() > 40)
|
|
{
|
|
sendSystemMessage(player, new string_id("beast", "name_too_long"));
|
|
sui.inputbox(self, player, "@beast:name_d", sui.OK_CANCEL, "@beast:name_t", sui.INPUT_NORMAL, null, "handleSetBeastName", null);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
sendDirtyObjectMenuNotification(self);
|
|
beast_lib.setBCDBeastName(beast_lib.getBeastBCD(self), beastName);
|
|
beast_lib.setBeastName(self, beastName);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handleGroupInvite(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int postCombatPathHome(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
LOGC(aiLoggingEnabled(self), "debug_ai", "pet::postCombatPathHome() self(" + self + ":" + getName(self) + ") master(" + getMaster(self) + ":" + getName(getMaster(self)) + ")");
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (ai_lib.isInCombat(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (utils.hasScriptVar(self, "ai.pet.staying"))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id guardTarget = utils.getObjIdScriptVar(self, "ai.pet.guarding");
|
|
if (isIdValid(guardTarget))
|
|
{
|
|
pet_lib.petFollow(self, guardTarget);
|
|
}
|
|
else if (hasObjVar(self, "ai.inFormation"))
|
|
{
|
|
ai_lib.resumeFormationFollowing(self);
|
|
}
|
|
else
|
|
{
|
|
obj_id master = getMaster(self);
|
|
if (isIdValid(master) && master.isLoaded())
|
|
{
|
|
pet_lib.petFollow(self, master);
|
|
}
|
|
else
|
|
{
|
|
stop(self);
|
|
}
|
|
}
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
public int handleAbandonment(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
int ignoredForDays = getIntObjVar(self, "ai.pet.ignoredForDays");
|
|
ignoredForDays++;
|
|
if (ignoredForDays > 3)
|
|
{
|
|
pet_lib.releasePet(self);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
else
|
|
{
|
|
setObjVar(self, "ai.pet.ignoredForDays", ignoredForDays);
|
|
}
|
|
messageTo(self, "handleAbandonment", null, 86400, false);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int resumePetTrick(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
obj_id master = params.getObjId("master");
|
|
int trickNum = params.getInt("trickNum");
|
|
pet_lib.doStupidPetTrick(self, master, trickNum);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnGiveItem(obj_id self, obj_id item, obj_id player) throws InterruptedException
|
|
{
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id master = getMaster(self);
|
|
if (!isIdValid(master))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
int pet_food = getIntObjVar(item, "race_restriction");
|
|
if (pet_lib.isCreaturePet(self) && (pet_food == -2) && (player == master))
|
|
{
|
|
food.petEatFood(self, master, item, player);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id petControlDevice = callable.getCallableCD(self);
|
|
obj_id petInv = utils.getInventoryContainer(petControlDevice);
|
|
if (!isIdValid(petInv))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (player != master)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (isMob(item))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
else if (!ai_lib.isNpc(self) || !ai_lib.isAndroid(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
putIn(item, petInv);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handleMoveToMaster(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id master = getMaster(self);
|
|
if (isIdValid(master))
|
|
{
|
|
location targetLocation = new location(getLocation(master));
|
|
targetLocation.x += rand(-4.0f, +4.0f);
|
|
targetLocation.z += rand(-4.0f, +4.0f);
|
|
targetLocation.y = getHeightAtLocation(targetLocation.x, targetLocation.z);
|
|
setLocation(self, getLocation(master));
|
|
pathTo(self, targetLocation);
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handlePackRequest(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
blog("handlePackRequest() destroying beast.");
|
|
if (!destroyObject(self))
|
|
{
|
|
debugServerConsoleMsg(null, "+++ beast.messageHandler handlePackRequest +++ WARNINGWARNING - FAILED TO DESTROY SELF");
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handleAddToStomach(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
int stomach = params.getInt("stomach");
|
|
int vol = params.getInt("vol");
|
|
player_stomach.addToStomach(self, stomach, vol);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handleSetColors(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
if (params == null || params.isEmpty())
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
setColors(self, params);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public boolean setColors(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
if (params == null || params.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
boolean litmus = true;
|
|
java.util.Enumeration keys = params.keys();
|
|
while (keys.hasMoreElements())
|
|
{
|
|
String var = (String)keys.nextElement();
|
|
int idx = params.getInt(var);
|
|
litmus &= hue.setColor(self, var, idx);
|
|
}
|
|
return litmus;
|
|
}
|
|
public int OnEnteredCombat(obj_id self) throws InterruptedException
|
|
{
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
obj_id master = getMaster(self);
|
|
if (isIdValid(master) && master.isLoaded())
|
|
{
|
|
aiSetHomeLocation(self, getLocation(master));
|
|
}
|
|
else
|
|
{
|
|
aiSetHomeLocation(self, getLocation(self));
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnDefenderCombatAction(obj_id self, obj_id attacker, obj_id weapon, int combatResult) throws InterruptedException
|
|
{
|
|
if (!beast_lib.getBeastDefensive(self))
|
|
{
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
if (utils.hasScriptVar(self, "petIgnoreAttacks"))
|
|
{
|
|
int timeStarted = utils.getIntScriptVar(self, "petIgnoreAttacks");
|
|
blog("OnDefenderCombatAction() beast hasScriptVar petIgnoreAttacks timeStarted: " + timeStarted + " getGameTime: " + getGameTime());
|
|
if (getGameTime() < (timeStarted + 20))
|
|
{
|
|
return SCRIPT_OVERRIDE;
|
|
}
|
|
utils.removeScriptVar(self, "petIgnoreAttacks");
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnSawAttack(obj_id self, obj_id defender, obj_id[] attackers) throws InterruptedException
|
|
{
|
|
if (beast_lib.isBeast(self) && beast_lib.getBeastDefensive(self))
|
|
{
|
|
for (final obj_id attacker : attackers) {
|
|
if (isIdValid(attacker) && !ai_lib.isInCombat(self) && defender == getMaster(self)) {
|
|
addHate(self, attacker, 0.0f);
|
|
}
|
|
}
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnExitedCombat(obj_id self) throws InterruptedException
|
|
{
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
utils.setScriptVar(self, "beast.combatEnded", getGameTime());
|
|
if (!utils.hasScriptVar(self, "ai.pet.staying"))
|
|
{
|
|
obj_id master = getMaster(self);
|
|
if (isIdValid(master) && master.isLoaded())
|
|
{
|
|
beast_lib.beastFollowTarget(self, master);
|
|
if (beast_lib.getBeastDefensive(self))
|
|
{
|
|
messageTo(self, "defensiveModePing", null, 1.0f, false);
|
|
}
|
|
if (!beast_lib.getBeastDefensive(self) && !utils.hasScriptVar(self, "petIgnoreAttacks"))
|
|
{
|
|
utils.setScriptVar(self, "petIgnoreAttacks", getGameTime());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aiSetHomeLocation(self, getLocation(self));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
obj_id master = getMaster(self);
|
|
if (isIdValid(master) && master.isLoaded())
|
|
{
|
|
beast_lib.doStayCommand(self, master);
|
|
}
|
|
else
|
|
{
|
|
ai_lib.aiStopFollowing(self);
|
|
location myLocation = getLocation(self);
|
|
setHomeLocation(self, myLocation);
|
|
setMovementWalk(self);
|
|
ai_lib.setDefaultCalmBehavior(self, ai_lib.BEHAVIOR_STOP);
|
|
}
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnSawEmote(obj_id self, obj_id performer, String emote) throws InterruptedException
|
|
{
|
|
obj_id master = getMaster(self);
|
|
if (performer != master)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (!isMob(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (!isPlayer(master))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (ai_lib.isInCombat(self) || ai_lib.isInCombat(master) || ai_lib.aiIsDead(self))
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (getLookAtTarget(master) != self)
|
|
{
|
|
if (getIntendedTarget(master) != self)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|
|
if (emote.startsWith("pet") || emote.equals("reassure") || emote.equals("nuzzle") || emote.equals("hug"))
|
|
{
|
|
if (rand(1, 2) == 1)
|
|
{
|
|
stop(self);
|
|
if (ai_lib.canSit(self))
|
|
{
|
|
if (rand(1, 2) == 1)
|
|
{
|
|
ai_lib.aiSetPosture(self, POSTURE_SITTING);
|
|
}
|
|
else
|
|
{
|
|
ai_lib.aiSetPosture(self, POSTURE_LYING_DOWN);
|
|
}
|
|
}
|
|
else if (ai_lib.canLieDown(self))
|
|
{
|
|
ai_lib.aiSetPosture(self, POSTURE_LYING_DOWN);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ai_lib.doAction(self, "happy");
|
|
}
|
|
}
|
|
else if (emote.equals("bonk") || emote.equals("whap") || emote.equals("scold") || emote.equals("bad") || emote.equals("slap"))
|
|
{
|
|
ai_lib.doAction(self, "ashamed");
|
|
}
|
|
else if (emote.equals("pointat") || emote.equals("tap"))
|
|
{
|
|
ai_lib.doAction(self, ai_lib.ACTION_ALERT);
|
|
}
|
|
else if (emote.equals("beckon") || emote.equals("summon"))
|
|
{
|
|
if (rand(1, 2) == 1)
|
|
{
|
|
ai_lib.doAction(self, "confused");
|
|
}
|
|
else
|
|
{
|
|
beast_lib.doFollowCommand(self, master);
|
|
}
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int OnDeath(obj_id self, obj_id killer, obj_id corpseId) throws InterruptedException
|
|
{
|
|
obj_id master = getMaster(self);
|
|
CustomerServiceLog("Beasts", "*Beast DEATH: (" + self + ": " + getName(self) + ") has died. Their master was, (" + master + " sid:" + getPlayerObject(master));
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int receiveCreditForKill(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
obj_id master = getMaster(self);
|
|
if (isIdValid(master))
|
|
{
|
|
String creatureName = params.getString("creatureName");
|
|
params.put("col_faction", dataTableGetString("datatables/mob/creatures.iff", creatureName, "col_faction"));
|
|
params.put("col_faction", dataTableGetInt("datatables/mob/creatures.iff", creatureName, "difficultyClass"));
|
|
messageTo(master, "receiveCreditForKill", params, 0.0f, false);
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int handleHealOverTimeTick(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
float duration = params.getFloat("duration");
|
|
float tick = params.getFloat("tick");
|
|
int heal = params.getInt("heal");
|
|
int hot_id = params.getInt("id");
|
|
int isCombat = params.getInt("combat");
|
|
obj_id medic = params.getObjId("medic");
|
|
if (isDead(self))
|
|
{
|
|
if (buff.hasBuff(self, "healOverTime"))
|
|
{
|
|
buff.removeBuff(self, "healOverTime");
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (!utils.hasScriptVar(self, healing.VAR_PLAYER_HOT_ID))
|
|
{
|
|
if (buff.hasBuff(self, "healOverTime"))
|
|
{
|
|
buff.removeBuff(self, "healOverTime");
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
int player_id = utils.getIntScriptVar(self, healing.VAR_PLAYER_HOT_ID);
|
|
if (hot_id != player_id)
|
|
{
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
if (!isIncapacitated(self))
|
|
{
|
|
int delta = healing.healDamage(medic, self, HEALTH, heal);
|
|
if (isCombat == 1 && isIdValid(medic))
|
|
{
|
|
prose_package pp = new prose_package();
|
|
pp = prose.setStringId(pp, new string_id("healing", "heal_fly"));
|
|
pp = prose.setDI(pp, delta);
|
|
pp = prose.setTO(pp, "HEALTH");
|
|
showFlyTextPrivateProseWithFlags(self, self, pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
|
|
if (medic != self)
|
|
{
|
|
showFlyTextPrivateProseWithFlags(self, medic, pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
|
|
}
|
|
pp = prose.setStringId(pp, healing.SID_PERFORM_HEAL_DAMAGE_SUCCESS);
|
|
pp = prose.setTT(pp, medic);
|
|
pp = prose.setTO(pp, self);
|
|
pp = prose.setDI(pp, delta);
|
|
healing.sendMedicalSpam(medic, self, pp, true, true, true, COMBAT_RESULT_MEDICAL);
|
|
delta = (int)(delta * healing.HEAL_OVER_TIME_AGGRO_REDUCER);
|
|
healing._addMedicalHate(medic, self, delta);
|
|
}
|
|
}
|
|
duration -= tick;
|
|
if (duration <= 0.0f)
|
|
{
|
|
if (buff.hasBuff(self, "healOverTime"))
|
|
{
|
|
buff.removeBuff(self, "healOverTime");
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
dictionary d = new dictionary();
|
|
d.put("duration", duration);
|
|
d.put("tick", tick);
|
|
d.put("heal", heal);
|
|
d.put("id", hot_id);
|
|
d.put("combat", isCombat);
|
|
d.put("medic", medic);
|
|
if (tick >= 0)
|
|
{
|
|
messageTo(self, healing.MSG_HEAL_OVER_TIME, d, tick, false);
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int defensiveModePing(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
obj_id master = getMaster(self);
|
|
if (isIdValid(master) && ai_lib.isInCombat(master))
|
|
{
|
|
obj_id[] masterAttackers = getHateList(master);
|
|
for (obj_id masterAttacker : masterAttackers) {
|
|
if (getHateTarget(masterAttacker) == master) {
|
|
utils.removeScriptVar(self, "petIgnoreAttacks");
|
|
startCombat(self, masterAttacker);
|
|
addHate(self, masterAttacker, 0.0f);
|
|
utils.setScriptVar(self, "ai.combat.target", masterAttacker);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
public int doBeastFlourish(obj_id self, dictionary params) throws InterruptedException
|
|
{
|
|
obj_id beast = (self);
|
|
int beastTrickNum = rand(1, 2);
|
|
doAnimationAction(beast, "trick_" + beastTrickNum);
|
|
return SCRIPT_CONTINUE;
|
|
}
|
|
}
|