Files
dsrc/sku.0/sys.server/compiled/game/script/library/target_dummy.scriptlib
T

1410 lines
45 KiB
Plaintext

/**********************************************************************
* Copyright (c)2008 Sony Online Entertainment Inc.
* All Rights Reserved
*
**********************************************************************/
/***** INCLUDES ********************************************************/
include library.combat;
include library.space_utils;
include library.sui;
include library.utils;
include java.util.Enumeration;
/***** LOGGING *******************************************************/
const string TERMINAL_LOGGING = "target_creature";
const boolean LOGGING_ON = true;
/***** CONSTANTS *******************************************************/
const string OWNER_OBJVAR = "targetDummyOwner";
const string CREATURE_NAME_OBJVAR = "targetDummyCreatureName";
const string TARGET_DUMMY_CONTROLLER_OBJVAR = "targetDummyController";
const string TARGET_DUMMY_ID_OBJVAR = "targetDummyId";
const string TARGET_DUMMY_SOUND_DELAY = "targetDummySoundDelay";
const string TARGET_DUMMY_NO_SOUND = "targetDummyNoSound";
const string[] TARGET_DUMMY_DEFENSES = {
"expertise_innate_protection_all",
"expertise_dodge",
"expertise_parry",
"expertise_block_chance",
"expertise_glancing_blow_all",
"expertise_evasion_chance"
};
const string BASE_TARGET_DUMMY_VAR = "target_dummy";
const string ALL_ATTACKS_SUB_VAR = "all_attacks";
const string LAST_ATTACK_TIME_VAR = "lastAttackTime";
const int PURGE_DATA_INTERVAL = 6*60*60; // hours x minutes per hour x seconds per minute
const int INDEX_NUM_OF_ATTACKS = 0;
const int INDEX_TOTAL_DAMAGE_DONE = 1;
const int INDEX_LARGEST_ATTACK = 2;
const int INDEX_SMALLEST_ATTACK = 3;
const int INDEX_NUM_CRITAL_HITS = 4;
const int INDEX_NUM_STRIKETHROUGH = 5;
const int INDEX_NUM_MISSED = 6;
const int INDEX_NUM_DODGED = 7;
const int INDEX_NUM_PARRIED = 8;
const int INDEX_NUM_GLANCING_HITS = 9;
const int INDEX_NUM_EVADED_HITS = 10;
const int INDEX_NUM_BLOCKED_HITS = 11;
const int INDEX_NUM_SUCCESSFUL_HITS = 12;
const int INDEX_NUM_NORMAL_HITS = 13;
const string[] ATTACK_DATA_ARRAY = {
"numAttacks",
"totalDamageDone",
"largestAttack",
"smallestAttack",
"numCriticalHits",
"numStrikethroughHit",
"numMissed",
"numDodged",
"numParried",
"numGlancingHit",
"numEvadedHit",
"numBlockedHit",
"numSuccessfulAttacks",
"numNormalHits"
};
// For output sui
const string_id REPORT_TITLE_SID = new string_id("target_dummy", "report_title");
const string_id REPORT_ATTACK_TYPE_SID = new string_id("target_dummy", "report_attack_type");
const string_id REPORT_NUM_ATTACKS_SID = new string_id("target_dummy", "report_num_attacks");
const string_id REPORT_TOTAL_DAMAGE_SID = new string_id("target_dummy", "report_total_damage");
const string_id REPORT_AVERAGE_DAMAGE_SID = new string_id("target_dummy", "report_average_damage");
const string_id REPORT_SMALLEST_ATTACK_SID = new string_id("target_dummy", "report_smallest_attack");
const string_id REPORT_LARGEST_ATTACK_SID = new string_id("target_dummy", "report_largest_attack");
const string_id REPORT_NUM_CRITS_SID = new string_id("target_dummy", "report_num_crits");
const string_id REPORT_NUM_STRIKETHROUGH_SID = new string_id("target_dummy", "report_num_strikethrough");
const string_id REPORT_NUM_MISSES_SID = new string_id("target_dummy", "report_num_misses");
const string_id REPORT_NUM_DODGES_SID = new string_id("target_dummy", "report_num_dodges");
const string_id REPORT_NUM_PARRIES_SID = new string_id("target_dummy", "report_num_parries");
const string_id REPORT_NUM_GLANCING_SID = new string_id("target_dummy", "report_num_glancing");
const string_id REPORT_NUM_EVADES_SID = new string_id("target_dummy", "report_num_evades");
const string_id REPORT_NUM_BLOCKED_SID = new string_id("target_dummy", "report_num_blocked");
const string_id REPORT_NUM_SUCCESSFUL_SID = new string_id("target_dummy", "report_num_successful_attacks");
const string_id REPORT_NUM_NORMAL_SID = new string_id("target_dummy", "report_num_normal_hits");
const string_id SID_TARGET_DUMMY_DIED_RESSURECTION = new string_id("target_dummy", "target_died_ressurected");
const string_id REPORT_LINE_BREAK_SID = new string_id("target_dummy", "report_line_break");
const string_id SID_SOUND_ANIMS_ON = new string_id("target_dummy", "sounds_anims_on");
const string_id SID_SOUND_ANIMS_OFF = new string_id("target_dummy", "sounds_anims_off");
const string_id REPORT_PERCENT_SIGN = new string_id("target_dummy", "report_percent");
const string GREEN = " \\#99FF33 ";
const string RED = " \\#FF3300 ";
const string ORANGE = " \\#FF8C00 ";
const string WHITE = " \\#FFFFFF ";
const string BLUE = " \\#0099FF ";
const string YELLOW = " \\#FFFF00 ";
const string LINE = " \n ";
//Target Dummy Animations
const string[] TARGET_DUMMY_ANIMS =
{
"shiver",
"shake_head_no",
"slump_head",
"beg",
"apologize",
"cover_eyes",
"cover_mouth",
"hands_above_head",
"hug_self",
"implore"
};
string addLineBreaks(int num)
{
string lineBreaks = "";
for(int i = 1; i <= num; i++)
{
lineBreaks += LINE;
}
return lineBreaks;
}
string percentSign()
{
return " "+utils.packStringId(REPORT_PERCENT_SIGN);
}
/***** FUNCTIONS *******************************************************/
boolean isTargetDummy(obj_id target)
{
return hasObjVar(target, "isTargetDummy");
}
// Called from OnObjectMenuSelect, so we validate the location.
obj_id createTargetDummy(obj_id controller, obj_id player)
{
if(!isValidId(controller) || !isValidId(player))
return obj_id.NULL_ID;
string creature = getTargetDummyCreatureType(controller);
if(creature == null || creature.equals(""))
return obj_id.NULL_ID;
if(creature.equals("tcg_target_dummy"))
{
if(isInWorldCell(player) || isInWorldCell(controller))
{
blog("Both are in world cell, abort");
return obj_id.NULL_ID;
}
location controllerLocation = getLocation(controller);
location awayLoc = utils.getRandomAwayLocation(controllerLocation, 1.f, 2.f);
if((awayLoc.cell != null) || isIdValid(awayLoc.cell))
awayLoc = controllerLocation;
if(!permittedToCallTargetDummy(player, awayLoc))
return obj_id.NULL_ID;
obj_id creatureObject = createTargetDummyAtLocation(controller, player, awayLoc);
messageTo(creatureObject, "faceThePlayer", null, 2, false);
messageTo(creatureObject, "checkCurrentLocation", null, 1, false);
return creatureObject;
}
else
{
location where = getLocation(controller);
if(!permittedToCallTargetDummy(player, where))
return obj_id.NULL_ID;
return createTargetDummyAtLocation(controller, player, where);
}
}
// Called from OnInitialize trigger.
// The Location should be legal based on check when player originally placed the controller.
obj_id recreateTargetDummy(obj_id controller, obj_id player)
{
if(isInWorldCell(controller))
return obj_id.NULL_ID;
location where = getLocation(controller);
obj_id targetDummyObj = createTargetDummyAtLocation(controller, player, where);
if(getTargetDummyCreatureType(controller).equals("tcg_target_dummy"))
{
float controllerYaw = getYaw(controller);
location offsetLoc = where;
offsetLoc.x += 2f;
location pathToLoc = utils.rotatePointXZ(where, offsetLoc, controllerYaw);
pathTo(targetDummyObj, pathToLoc);
setYaw(targetDummyObj, controllerYaw);
messageTo(targetDummyObj, "checkCurrentLocation", null, 1, false);
}
return targetDummyObj;
}
obj_id createTargetDummyAtLocation(obj_id controller, obj_id player, location createLoc)
{
obj_id npc = obj_id.NULL_ID;
obj_id owner = getTargetDummyOwnerFromController(controller);
if ( isIdValid(owner) )
{
string toCreate = getTargetDummyCreatureType(controller);
npc = create.object(toCreate, createLoc);
if ( isIdValid(npc) )
{
float controllerYaw = getYaw(controller);
if ( exists(player) )
{
location playerLoc = getLocation(player);
if ( playerLoc.cell == createLoc.cell )
{
faceTo(npc, player);
}
else
{
setYaw(npc, controllerYaw);
}
}
else
{
setYaw(npc, controllerYaw);
}
obj_id structure = getTopMostContainer(controller);
if ( isIdValid(structure) && isGameObjectTypeOf(structure, GOT_building_player) )
{
permissionsAddAllowed(structure, npc.toString());
}
setObjVar(npc, OWNER_OBJVAR, owner);
setObjVar(npc, TARGET_DUMMY_CONTROLLER_OBJVAR, controller);
setObjVar(controller, TARGET_DUMMY_ID_OBJVAR, npc);
ai_lib.setDefaultCalmBehavior(npc, ai_lib.BEHAVIOR_SENTINEL);
string planet = createLoc.area;
if( planet.startsWith("space_") )
{
setInvulnerable(npc, true);
}
}
}
return npc;
}
void cleanupTargetDummy(obj_id controller, obj_id targetDummy)
{
removeObjVar(controller, target_dummy.TARGET_DUMMY_ID_OBJVAR);
removeTargetDummyFromPermissions(targetDummy);
destroyObject(targetDummy);
return;
}
void removeTargetDummyFromPermissions(obj_id targetDummy)
{
obj_id structure = getTopMostContainer(targetDummy);
if ( isIdValid(structure) )
{
if ( player_structure.isNameOnEntryList(structure, targetDummy.toString()) )
{
permissionsRemoveAllowed(structure, targetDummy.toString());
}
}
return;
}
void removeTargetDummyFromPermissionsViaController(obj_id controller, obj_id targetDummy)
{
obj_id structure = getTopMostContainer(controller);
if ( isIdValid(structure) )
{
if ( player_structure.isNameOnEntryList(structure, targetDummy.toString()) )
{
permissionsRemoveAllowed(structure, targetDummy.toString());
}
}
return;
}
obj_id setTargetDummyOwner(obj_id controller)
{
obj_id owner = getOwner(controller);
if(isIdValid(owner))
{
return owner;
}
else
{
CustomerServiceLog("target_dummy", "target_dummy.scriptlib:setTargetDummyOwner - The Target Dummy System is attempting to assign an owner for controller: "+controller);
owner = utils.getContainingPlayer(controller);
if ( isIdValid(owner) )
{
setOwner(controller, owner);
CustomerServiceLog("target_dummy", "target_dummy.scriptlib:setTargetDummyOwner - Target Dummy Controller: "+controller+" Ownership given to Owner OID: "+owner);
}
else
{
//LOG("target_dummy", "Target dummy owner was null and could not find a containing player.");
}
}
return owner;
}
obj_id getTargetDummyOwnerFromController(obj_id controller)
{
return getOwner(controller);
}
obj_id getTargetDummyController(obj_id targetDummy)
{
obj_id controller = obj_id.NULL_ID;
if ( hasObjVar(targetDummy, TARGET_DUMMY_CONTROLLER_OBJVAR) )
{
controller = getObjIdObjVar(targetDummy, TARGET_DUMMY_CONTROLLER_OBJVAR);
}
return controller;
}
obj_id getTargetDummyId(obj_id controller)
{
obj_id targetDummy = obj_id.NULL_ID;
if ( hasObjVar(controller, TARGET_DUMMY_ID_OBJVAR) )
{
targetDummy = getObjIdObjVar(controller, TARGET_DUMMY_ID_OBJVAR);
}
return targetDummy;
}
string getTargetDummyCreatureType(obj_id controller)
{
string targetDummyCreatureType = "tcg_target_creature_acklay";
if ( hasObjVar(controller, target_dummy.CREATURE_NAME_OBJVAR) )
{
targetDummyCreatureType = getStringObjVar(controller, target_dummy.CREATURE_NAME_OBJVAR);
}
return targetDummyCreatureType;
}
boolean permittedToCallTargetDummy(obj_id player, location here)
{
if( !isIdValid(player) || here == null )
{
return false;
}
// God mode override to allow event team to place storyteller items with more freedom
if ( isGod(player) )
{
string logMsg = "("+player+")"+getName(player)+" is using GodMode override to deploy a target dummy at "+here;
CustomerServiceLog("target_dummy", logMsg);
sendSystemMessage(player, new string_id("target_dummy", "placement_god_mode"));
return true;
}
obj_id myCell = here.cell;
obj_id myContainer = getTopMostContainer(myCell);
string planet = here.area;
if( planet.startsWith("space_") )
{
obj_id owner= getOwner(myContainer);
if ( !isIdValid(owner) || owner != player )
{
sendSystemMessage(player, new string_id("target_dummy", "placement_not_ship_owner"));
return false;
}
if ( getState(player, STATE_SHIP_INTERIOR) != 1 || space_utils.isInStation(player) )
{
sendSystemMessage(player, new string_id("target_dummy", "placement_not_in_station"));
return false;
}
}
else
{
if( !isIdValid(myCell) )
{
sendSystemMessage(player, new string_id("target_dummy", "placement_not_outside"));
return false;
}
else if ( !player_structure.isAdmin(myContainer, player) )
{
sendSystemMessage(player, new string_id("target_dummy", "placement_not_building_admin"));
return false;
}
}
return true;
}
boolean controllerContainmentCheck(obj_id controller)
{
if ( !utils.isNestedWithinAPlayer(controller) )
{
obj_id building = getTopMostContainer(controller);
if ( isGameObjectTypeOf(building, GOT_building_player) || ( isGameObjectTypeOf(building, GOT_ship_fighter) && space_utils.isShipWithInterior(building) ) )
{
location here = getLocation(controller);
if ( getContainedBy(controller) == here.cell )
{
return true;
}
}
}
return false;
}
boolean initializeTargetDummy(obj_id targetDummy, int combatLevel, int difficulty)
{
boolean result = false;
string creatureName = getCreatureName(targetDummy);
dictionary creatureDict = utils.dataTableGetRow(create.CREATURE_TABLE, creatureName);
if ( creatureDict != null )
{
creatureDict.put("difficultyClass", difficulty);
create.initializeCreature(targetDummy, creatureName, creatureDict, combatLevel);
setNpcDifficulty(targetDummy, difficulty);
result = false;
obj_id controller = target_dummy.getTargetDummyController(targetDummy);
if ( isIdValid(controller) )
{
setObjVar(controller, "intCombatDifficulty", combatLevel);
setObjVar(controller, "difficultyClass", difficulty);
}
}
return result;
}
int getTargetDummyDifficulty(obj_id targetDummy)
{
int difficulty = 0;
if ( hasObjVar(targetDummy, "difficultyClass") )
{
difficulty = getIntObjVar(targetDummy, "difficultyClass");
}
return difficulty;
}
int getTargetDummyCombatLevel(obj_id targetDummy)
{
int level = 50;
if ( hasObjVar(targetDummy, "intCombatDifficulty") )
{
level = getIntObjVar(targetDummy, "intCombatDifficulty");
}
return level;
}
void promptForCombatLevel(obj_id targetDummy, obj_id player)
{
string prompt = utils.packStringId(new string_id("target_dummy", "combat_level_prompt"));
string name = utils.packStringId(new string_id("target_dummy", "combat_level_name"));
//sui.inputbox(targetDummy, player, prompt, "handleTargetDummyLevelSelect");
sui.inputbox(targetDummy, player, prompt, sui.OK_CANCEL, name, sui.INPUT_NORMAL, null, "handleTargetDummyLevelSelect", null);
return;
}
void promptForCombatDifficulty(obj_id targetDummy, obj_id player)
{
string title = utils.packStringId(new string_id("target_dummy", "combat_difficulty_title"));
string prompt = utils.packStringId(new string_id("target_dummy","combat_difficulty_prompt"));
string normal = utils.packStringId(new string_id("target_dummy", "difficulty_normal"));
string elite = utils.packStringId(new string_id("target_dummy", "difficulty_elite"));
string boss = utils.packStringId(new string_id("target_dummy", "difficulty_boss"));
string [] difficulties = { normal, elite, boss };
int pid = sui.listbox(targetDummy, player, prompt, sui.OK_CANCEL, title, difficulties, "handleTargetDummyDifficultySelect");
return;
}
void showTargetDummyDefenseListSui(obj_id targetDummy, obj_id player)
{
if ( utils.hasScriptVar(player, "targetDummy.pidTargetDummyDefenses") )
{
int oldPid = utils.getIntScriptVar(player, "targetDummy.pidTargetDummyDefenses");
forceCloseSUIPage(oldPid);
}
string title = utils.packStringId(new string_id("target_dummy", "combat_set_defenses_title"));
string prompt = utils.packStringId(new string_id("target_dummy","combat_set_defenses_prompt"));
int pid = sui.listbox(targetDummy, player, prompt, sui.OK_CANCEL, title, getTargetDummySkillModsOptions(targetDummy), "targetDummyDefenseTypeSelected");
if ( pid > -1 )
{
utils.setScriptVar(player, "targetDummy.pidTargetDummyDefenses", pid);
}
return;
}
string[] getTargetDummySkillModsOptions(obj_id targetDummy)
{
string[] targetDummySkillMods = new string[TARGET_DUMMY_DEFENSES.length];
for ( int i=0; i < TARGET_DUMMY_DEFENSES.length; i++ )
{
string skillModName = TARGET_DUMMY_DEFENSES[i];
string skillModOption = utils.packStringId(new string_id("target_dummy", TARGET_DUMMY_DEFENSES[i]));
targetDummySkillMods[i] = skillModOption + " [current value: " + getEnhancedSkillStatisticModifier(targetDummy, skillModName) + "]";
}
return targetDummySkillMods;
}
void promptForDefensiveValue(obj_id targetDummy, obj_id player, int skill_mod_selected)
{
utils.setScriptVar(player, "targetDummySkillModSelected", skill_mod_selected);
string prompt = utils.packStringId(new string_id("target_dummy", "combat_defensive_skill_mod_prompt"));
prompt += " " + utils.packStringId(new string_id("target_dummy", target_dummy.TARGET_DUMMY_DEFENSES[skill_mod_selected])) +" :";
sui.inputbox(targetDummy, player, prompt, "handleTargetDummyDefensiveSkillModSet");
return;
}
void setTargetDummyDefensiveValue(obj_id targetDummy, obj_id player, int value)
{
int skillModIndex = utils.getIntScriptVar(player, "targetDummySkillModSelected");
string skillModName = target_dummy.TARGET_DUMMY_DEFENSES[skillModIndex];
setTargetDummyDefensiveValue(targetDummy, player, value, skillModName);
return;
}
void setTargetDummyDefensiveValue(obj_id targetDummy, obj_id player, int value, string skillModName)
{
int previousValue = getEnhancedSkillStatisticModifier(targetDummy, skillModName);
if ( skillModName.equals("expertise_innate_protection_all") )
{
if ( value < 0 || value > 12000 )
{
if ( isIdValid(player) )
{
sendSystemMessage(player, new string_id("target_dummy", "combat_armor_mod_invalid"));
return;
}
}
else
{
// First setting the skill mod to 0 so that the value that was input will be the new total value
applySkillStatisticModifier(targetDummy, skillModName, 0-previousValue);
applySkillStatisticModifier(targetDummy, skillModName, value);
armor.recalculateArmorForMob(targetDummy);
}
}
else
{
if ( value < 0 || value > 99 )
{
if ( isIdValid(player) )
{
sendSystemMessage(player, new string_id("target_dummy", "combat_skill_mod_invalid"));
return;
}
}
else
{
// First setting the skill mod to 0 so that the value that was input will be the new total value
applySkillStatisticModifier(targetDummy, skillModName, 0-previousValue);
applySkillStatisticModifier(targetDummy, skillModName, value);
}
}
if ( isIdValid(player) )
{
string_id message = new string_id ("target_dummy", "combat_skill_mod_set");
prose_package pp = prose.getPackage(message, player, player);
prose.setTO(pp, utils.packStringId(new string_id("target_dummy", skillModName)));
prose.setDI(pp, value);
sendSystemMessageProse(player, pp);
}
obj_id controller = getTargetDummyController(targetDummy);
if ( isIdValid(controller) )
{
setObjVar(controller, "target_dummy_defense."+skillModName, value);
}
return;
}
void confirmClearYourCombatData(obj_id targetDummy, obj_id player)
{
string title = utils.packStringId(new string_id("target_dummy", "data_cleared_confirm_title"));
string prompt = utils.packStringId(new string_id("target_dummy", "data_cleared_confirm_prompt"));
string handler = "confirmClearYourCombatData";
buildConfirmClearCombatDataSui(targetDummy, player, title, prompt, handler);
return;
}
void confirmClearAllCombatData(obj_id targetDummy, obj_id player)
{
string title = utils.packStringId(new string_id("target_dummy", "data_all_cleared_confirm_title"));
string prompt = utils.packStringId(new string_id("target_dummy", "data_all_cleared_confirm_prompt"));
string handler = "confirmClearAllCombatData";
buildConfirmClearCombatDataSui(targetDummy, player, title, prompt, handler);
return;
}
void buildConfirmClearCombatDataSui(obj_id targetDummy, obj_id player, string title, string prompt, string handler)
{
string ok_button = utils.packStringId(new string_id ("quest/ground/util/quest_giver_object", "button_accept"));
string cancel_button = utils.packStringId(new string_id ("quest/ground/util/quest_giver_object", "button_decline"));
// Create the dialog page.
int pid = sui.createSUIPage( sui.SUI_MSGBOX, targetDummy, player, handler);
// Add elements text.
setSUIProperty(pid, sui.MSGBOX_TITLE, sui.PROP_TEXT, title);
setSUIProperty(pid, sui.MSGBOX_PROMPT, sui.PROP_TEXT, prompt);
// Add buttons.
sui.msgboxButtonSetup(pid, sui.YES_NO);
setSUIProperty(pid, sui.MSGBOX_BTN_OK, sui.PROP_TEXT, ok_button);
setSUIProperty(pid, sui.MSGBOX_BTN_CANCEL, sui.PROP_TEXT, cancel_button);
// Show dialog.
utils.setScriptVar(player, "clearCombatData.openSui", pid);
sui.showSUIPage( pid );
return;
}
void clearYourCombatData(obj_id targetDummy, obj_id player)
{
obj_id controller = getTargetDummyController(targetDummy);
if ( isIdValid(controller) && utils.hasScriptVarTree(controller, BASE_TARGET_DUMMY_VAR+"."+player) )
{
utils.removeScriptVarTree(controller, BASE_TARGET_DUMMY_VAR+"."+player);
sendSystemMessage(player, new string_id("target_dummy", "combat_data_clearing"));
sendSystemMessage(player, new string_id("target_dummy", "combat_data_cleared"));
// remove old combat data objvar that would have destroyed the entire game
if ( hasObjVar(controller, target_dummy.BASE_TARGET_DUMMY_VAR) )
{
removeObjVar(controller, target_dummy.BASE_TARGET_DUMMY_VAR);
}
}
return;
}
void clearAllCombatData(obj_id targetDummy, obj_id player)
{
obj_id controller = getTargetDummyController(targetDummy);
if ( isIdValid(controller) && utils.hasScriptVarTree(controller, BASE_TARGET_DUMMY_VAR) )
{
utils.removeScriptVarTree(controller, BASE_TARGET_DUMMY_VAR);
sendSystemMessage(player, new string_id("target_dummy", "combat_data_all_clearing"));
sendSystemMessage(player, new string_id("target_dummy", "combat_data_all_cleared"));
// remove old combat data objvar that would have destroyed the entire game
if ( hasObjVar(controller, target_dummy.BASE_TARGET_DUMMY_VAR) )
{
removeObjVar(controller, target_dummy.BASE_TARGET_DUMMY_VAR);
}
}
return;
}
void sendTargetDummyCombatData(obj_id attacker, obj_id defender, combat_data actionData, hit_result hitData)
{
// this first check is currently intended for internal testing an stores the combat data on the attacker
if ( utils.hasScriptVar(attacker, "testing_recordCombatData") )
{
recoredCombatResult(attacker, attacker, actionData, hitData);
}
// if the defender is a target dummy, we store combat data on the defender
if ( isTargetDummy(defender) )
{
recoredCombatResultViaController(attacker, defender, actionData, hitData);
}
return;
}
void recoredCombatResultViaController(obj_id attacker, obj_id targetDummy, combat_data actionData, hit_result hitData)
{
obj_id controller = getTargetDummyController(targetDummy);
if ( isIdValid(controller) )
{
recoredCombatResult(attacker, controller, actionData, hitData);
}
return;
}
void recoredCombatResult(obj_id attacker, obj_id controller, combat_data actionData, hit_result hitData)
{
string attackUsed = actionData.actionName;
boolean attackMissed = hitData.miss;
boolean attackDodged = hitData.dodge;
boolean attackParried = hitData.parry;
int damageDone = hitData.damage;
boolean criticalHit = hitData.critical;
int criticalDamage = hitData.critDamage;
boolean strikethroughHit = hitData.strikethrough;
float strikethroughAmmount = hitData.strikethroughAmmount;
boolean glancingHit = hitData.glancing;
boolean evadedDamage = hitData.evadeResult;
float evadeAmmount = hitData.evadeAmmount;
boolean blockedHit = hitData.blockResult;
int blockAmount = hitData.block;
obj_id combatDataOwner = attacker;
if ( beast_lib.isBeast(attacker) )
{
combatDataOwner = getMaster(attacker);
}
string baseAttackerVar = BASE_TARGET_DUMMY_VAR+"."+combatDataOwner;
string baseAllAttacksVar = baseAttackerVar+"."+ ALL_ATTACKS_SUB_VAR;
string baseSpecificAttackVar = baseAttackerVar+"."+attackUsed;
int[] allAttacksData = new int[ATTACK_DATA_ARRAY.length];
if ( utils.hasScriptVarTree(controller, baseAllAttacksVar) )
{
allAttacksData = utils.getIntArrayScriptVar(controller, baseAllAttacksVar);
}
else
{
for ( int i = 0; i < allAttacksData.length; i++ )
{
allAttacksData[i] = 0;
}
}
int[] specificAttackData = new int[ATTACK_DATA_ARRAY.length];
if ( utils.hasScriptVarTree(controller, baseSpecificAttackVar) )
{
specificAttackData = utils.getIntArrayScriptVar(controller, baseSpecificAttackVar);
}
else
{
for ( int i = 0; i < specificAttackData.length; i++ )
{
specificAttackData[i] = 0;
}
}
storeCumulativeCombatData(allAttacksData, INDEX_NUM_OF_ATTACKS, 1);
storeCumulativeCombatData(specificAttackData, INDEX_NUM_OF_ATTACKS, 1);
// No damage...attack was dodged, parried, or just missed.
if ( !hitData.success )
{
//sendSystemMessage(combatDataOwner, "An attack was missed, dodged, or parried...", "");
int indexOfAvoidanceType = -1;
int numAvoided = 1;
if ( attackMissed )
{
indexOfAvoidanceType = INDEX_NUM_MISSED;
}
else if ( attackDodged )
{
indexOfAvoidanceType = INDEX_NUM_DODGED;
}
else if ( attackParried )
{
indexOfAvoidanceType = INDEX_NUM_PARRIED;
}
else
{
// the attack was unsuccessful for some other reason.
// The target dummy is going to call that a Miss.
indexOfAvoidanceType = INDEX_NUM_MISSED;
}
if ( indexOfAvoidanceType > -1 )
{
storeCumulativeCombatData(allAttacksData, indexOfAvoidanceType, 1);
storeCumulativeCombatData(specificAttackData, indexOfAvoidanceType, 1);
}
}
else // Some damage was done. Recording the results.
{
// total amount of damage done this session from all attacks
storeCumulativeCombatData(allAttacksData, INDEX_TOTAL_DAMAGE_DONE, damageDone);
// get largest and smallest overall individual attack
storeComparisonCombatData(allAttacksData, damageDone);
// damage done by attack type
storeCumulativeCombatData(specificAttackData, INDEX_TOTAL_DAMAGE_DONE, damageDone);
// get largest and smallest attack by type
storeComparisonCombatData(specificAttackData, damageDone);
// critical hit data
if ( criticalHit )
{
storeCumulativeCombatData(allAttacksData, INDEX_NUM_CRITAL_HITS, 1);
storeCumulativeCombatData(specificAttackData, INDEX_NUM_CRITAL_HITS, 1);
}
// strikethrough hit data
if ( strikethroughHit )
{
storeCumulativeCombatData(allAttacksData, INDEX_NUM_STRIKETHROUGH, 1);
storeCumulativeCombatData(specificAttackData, INDEX_NUM_STRIKETHROUGH, 1);
}
// glancing hit data
if ( glancingHit )
{
storeCumulativeCombatData(allAttacksData, INDEX_NUM_GLANCING_HITS, 1);
storeCumulativeCombatData(specificAttackData, INDEX_NUM_GLANCING_HITS, 1);
}
// evaded damage data
if ( evadedDamage )
{
storeCumulativeCombatData(allAttacksData, INDEX_NUM_EVADED_HITS, 1);
storeCumulativeCombatData(specificAttackData, INDEX_NUM_EVADED_HITS, 1);
}
// blocked hit data
if ( blockedHit )
{
storeCumulativeCombatData(allAttacksData, INDEX_NUM_BLOCKED_HITS, 1);
storeCumulativeCombatData(specificAttackData, INDEX_NUM_BLOCKED_HITS, 1);
}
// total successful attacks
storeCumulativeCombatData(allAttacksData, INDEX_NUM_SUCCESSFUL_HITS, 1);
storeCumulativeCombatData(specificAttackData, INDEX_NUM_SUCCESSFUL_HITS, 1);
// num normal hits
if ( recordAsNormalHit(hitData) )
{
storeCumulativeCombatData(allAttacksData, INDEX_NUM_NORMAL_HITS, 1);
storeCumulativeCombatData(specificAttackData, INDEX_NUM_NORMAL_HITS, 1);
}
}
utils.setScriptVar(controller, baseAllAttacksVar, allAttacksData);
utils.setScriptVar(controller, baseSpecificAttackVar, specificAttackData);
utils.setScriptVar(controller, baseAttackerVar + "." + LAST_ATTACK_TIME_VAR, getGameTime());
return;
}
void storeCumulativeCombatData(int[] dataArray, int index, int newData)
{
int previousData = dataArray[index];
dataArray[index] = previousData + newData;
return;
}
void storeComparisonCombatData(int[] dataArray, int newData)
{
int previousLargest = dataArray[INDEX_LARGEST_ATTACK];
if ( newData >= previousLargest )
{
dataArray[INDEX_LARGEST_ATTACK] = newData;
}
int previousSmallest = newData;
if ( dataArray[INDEX_SMALLEST_ATTACK] > 0 )
{
previousSmallest = dataArray[INDEX_SMALLEST_ATTACK];
}
if ( newData <= previousSmallest )
{
dataArray[INDEX_SMALLEST_ATTACK] = newData;
}
return;
}
boolean recordAsNormalHit(hit_result hitData)
{
boolean criticalHit = hitData.critical;
boolean strikethroughHit = hitData.strikethrough;
boolean glancingHit = hitData.glancing;
boolean evadedDamage = hitData.evadeResult;
boolean blockedHit = hitData.blockResult;
if ( !criticalHit && !strikethroughHit )
{
return true;
}
return false;
}
void reportCombatData(obj_id player, obj_id targetDummy)
{
reportCombatDataViaController(player, targetDummy, obj_id.NULL_ID);
return;
}
void reportCombatDataViaController(obj_id player, obj_id targetDummy, obj_id controller)
{
// If the control object isn't null, that is where the report data should be.
// Otherwise it should be on the object sent as the targetDummy
obj_id reportDataObject = targetDummy;
if ( isIdValid(controller) )
{
reportDataObject = controller;
}
// remove old combat data objvar that would have destroyed the entire game
if ( hasObjVar(reportDataObject, target_dummy.BASE_TARGET_DUMMY_VAR) )
{
removeObjVar(reportDataObject, target_dummy.BASE_TARGET_DUMMY_VAR);
}
string baseAttackerVar = BASE_TARGET_DUMMY_VAR+"."+player;
if ( utils.hasScriptVarTree(reportDataObject, baseAttackerVar) )
{
string report = getCombatDataReportString(reportDataObject, player);
if ( utils.hasScriptVar(player, "target_dummy.openCombatReportSui") )
{
int oldPid = utils.getIntScriptVar(player, "target_dummy.openCombatReportSui");
forceCloseSUIPage(oldPid);
}
// Create the dialog page.
int pid = sui.createSUIPage(sui.SUI_MSGBOX, targetDummy, player, "handleTargetDummyCombatReport");
// Add elements text.
setSUIProperty(pid, sui.MSGBOX_TITLE, sui.PROP_TEXT, utils.packStringId(new string_id("target_dummy", "report_title")) );
setSUIProperty(pid, sui.MSGBOX_PROMPT, sui.PROP_TEXT, report);
// Add buttons.
sui.msgboxButtonSetup(pid, sui.YES_NO_CANCEL);
setSUIProperty(pid, sui.MSGBOX_BTN_OK, sui.PROP_TEXT, utils.packStringId(new string_id("target_dummy", "report_refreshbutton")));
setSUIProperty(pid, sui.MSGBOX_BTN_REVERT, sui.PROP_TEXT, utils.packStringId(new string_id("target_dummy", "report_clear_button")));
setSUIProperty(pid, sui.MSGBOX_BTN_CANCEL, sui.PROP_TEXT, utils.packStringId(new string_id("target_dummy", "report_closebutton")));
setSUIProperty(pid, sui.MSGBOX_BTN_REVERT, "OnPress", "RevertWasPressed=1\r\nparent.btnOk.press=t");
subscribeToSUIProperty(pid, sui.MSGBOX_BTN_REVERT, "RevertWasPressed");
// Show dialog.
utils.setScriptVar(player, "target_dummy.openCombatReportSui", pid);
sui.showSUIPage(pid);
}
else
{
sendSystemMessage(player, new string_id("target_dummy", "placement_no_combat_data"));
}
return;
}
string getCombatDataReportString(obj_id reportDataObject, obj_id player)
{
string report = "";
string baseAttackerVar = BASE_TARGET_DUMMY_VAR+"."+player;
if ( utils.hasScriptVarTree(reportDataObject, baseAttackerVar) )
{
deltadictionary vars = reportDataObject.getScriptVars();
resizeable string[] attackTypes = new string[];
Enumeration keys = vars.keys();
while ( keys.hasMoreElements() )
{
string key = (string)(keys.nextElement());
if ( key.startsWith(baseAttackerVar + ".") )
{
string[] data = split(key, '.');
// data[0] = target_dummy
// data[1] = player obj_id
// data[2] = attack type
string attackType = data[2];
if ( !attackType.equals(LAST_ATTACK_TIME_VAR) )
{
utils.addElement(attackTypes, attackType);
}
}
}
int numItems = attackTypes.length;
string[] initialAttackTypes = new string[numItems-1];
int[] initialDamageDoneArray = new int[numItems-1];
string[] sortedAttackTypes = new string[numItems];
int initialIdx = 0;
for ( int i = 0; i < numItems; i++ )
{
string attackName = attackTypes[i];
if ( attackName.equals(ALL_ATTACKS_SUB_VAR) )
{
sortedAttackTypes[0] = attackName;
}
else
{
initialAttackTypes[initialIdx] = attackName;
string baseSpecificAttackVar = baseAttackerVar+"."+attackName;
int[] tempAttackData = utils.getIntArrayScriptVar(reportDataObject, baseSpecificAttackVar);
initialDamageDoneArray[initialIdx] = tempAttackData[INDEX_TOTAL_DAMAGE_DONE];
initialIdx = initialIdx + 1;
}
}
int[] ascendingDataArray = new int[initialDamageDoneArray.length];
utils.copyArray(initialDamageDoneArray, ascendingDataArray);
Arrays.sort(ascendingDataArray);
for ( int j = 0; j < ascendingDataArray.length; j++ )
{
int data = ascendingDataArray[j];
int index = utils.getElementPositionInArray(initialDamageDoneArray, data);
string name = initialAttackTypes[index];
sortedAttackTypes[(ascendingDataArray.length) - j] = name;
initialDamageDoneArray[index] = -1;
}
int numAttackTypes = sortedAttackTypes.length;
report = utils.packStringId(REPORT_TITLE_SID) + addLineBreaks(1);
for ( int idx = 0; idx < numAttackTypes; idx++ )
{
string attackTypeName = sortedAttackTypes[idx];
string attackTypeVarName = baseAttackerVar+"."+attackTypeName;
int[] attackData = utils.getIntArrayScriptVar(reportDataObject, attackTypeVarName);
int numAttacks = attackData[INDEX_NUM_OF_ATTACKS];
int totalDamageDone = attackData[INDEX_TOTAL_DAMAGE_DONE];
int largestAttack = attackData[INDEX_LARGEST_ATTACK];
int smallestAttack = attackData[INDEX_SMALLEST_ATTACK];
int numCriticalHits = attackData[INDEX_NUM_CRITAL_HITS];
int numStrikethroughHit = attackData[INDEX_NUM_STRIKETHROUGH];
int numMissed = attackData[INDEX_NUM_MISSED];
int numDodged = attackData[INDEX_NUM_DODGED];
int numParried = attackData[INDEX_NUM_PARRIED];
int numGlancingHit = attackData[INDEX_NUM_GLANCING_HITS];
int numEvadedDamage = attackData[INDEX_NUM_EVADED_HITS];
int numBlockedHit = attackData[INDEX_NUM_BLOCKED_HITS];
int numSuccessfulAttacks = attackData[INDEX_NUM_SUCCESSFUL_HITS];
int numNormalHits = attackData[INDEX_NUM_NORMAL_HITS];
int averageDamage = totalDamageDone/numAttacks;
float percentageMissed = getPercentage(numMissed, numAttacks);
float percentageDodged = getPercentage(numDodged, numAttacks);
float percentageParried = getPercentage(numParried, numAttacks);
float percentageCrit = getPercentage(numCriticalHits, numAttacks);
float percentageStrikethrough = getPercentage(numStrikethroughHit, numAttacks);
float percentageGlancing = getPercentage(numGlancingHit, numAttacks);
float percentageEvaded = getPercentage(numEvadedDamage, numAttacks);
float percentageBlocked = getPercentage(numBlockedHit, numAttacks);
float percentageNormal = getPercentage(numNormalHits, numAttacks);
report += YELLOW + utils.packStringId(REPORT_ATTACK_TYPE_SID);
report += WHITE + utils.packStringId(new string_id("cmd_n", attackTypeName)) + addLineBreaks(1);
report += GREEN + utils.packStringId(REPORT_NUM_ATTACKS_SID) + WHITE + numAttacks + addLineBreaks(1);
report += GREEN + utils.packStringId(REPORT_TOTAL_DAMAGE_SID) + WHITE + totalDamageDone + addLineBreaks(1);
report += GREEN + utils.packStringId(REPORT_AVERAGE_DAMAGE_SID) + WHITE + averageDamage + addLineBreaks(1);
report += GREEN + utils.packStringId(REPORT_SMALLEST_ATTACK_SID) + WHITE + smallestAttack + addLineBreaks(1);
report += GREEN + utils.packStringId(REPORT_LARGEST_ATTACK_SID) + WHITE + largestAttack + addLineBreaks(2);
report += BLUE + utils.packStringId(REPORT_NUM_SUCCESSFUL_SID) + WHITE + numSuccessfulAttacks + addLineBreaks(1);
// report += BLUE + utils.packStringId(REPORT_NUM_NORMAL_SID) + WHITE + numNormalHits + " ( "+ percentageNormal+ percentSign() + addLineBreaks(1);
report += BLUE + utils.packStringId(REPORT_NUM_CRITS_SID) + WHITE + numCriticalHits + " ( "+ percentageCrit+ percentSign() + addLineBreaks(1);
report += BLUE + utils.packStringId(REPORT_NUM_STRIKETHROUGH_SID) + WHITE + numStrikethroughHit + " ( " + percentageStrikethrough + percentSign() + addLineBreaks(2);
report += ORANGE + utils.packStringId(REPORT_NUM_GLANCING_SID) + WHITE + numGlancingHit + " ( " + percentageGlancing + percentSign() + addLineBreaks(1);
report += ORANGE + utils.packStringId(REPORT_NUM_EVADES_SID) + WHITE + numEvadedDamage + " ( " + percentageEvaded + percentSign() + addLineBreaks(1);
report += ORANGE + utils.packStringId(REPORT_NUM_BLOCKED_SID) + WHITE + numBlockedHit + " ( " + percentageBlocked + percentSign() + addLineBreaks(2);
report += RED + utils.packStringId(REPORT_NUM_MISSES_SID) + WHITE + numMissed + " ( " + percentageMissed + percentSign() + addLineBreaks(1);
report += RED + utils.packStringId(REPORT_NUM_DODGES_SID) + WHITE + numDodged + " ( " + percentageDodged + percentSign() + addLineBreaks(1);
report += RED + utils.packStringId(REPORT_NUM_PARRIES_SID) + WHITE + numParried + " ( "+ percentageParried + percentSign() + addLineBreaks(1);
report += WHITE + utils.packStringId(REPORT_LINE_BREAK_SID)+ addLineBreaks(2);
}
}
else
{
report = utils.packStringId(new string_id("target_dummy", "placement_no_combat_data"));
}
return report;
}
void showRawCombatDataViaController(obj_id player, obj_id targetDummy)
{
if ( isGod(player) )
{
obj_id controller = target_dummy.getTargetDummyController(targetDummy);
if ( isIdValid(controller) )
{
showRawCombatData(player, controller);
}
}
return;
}
void showRawCombatData(obj_id player, obj_id controller)
{
if ( isGod(player) )
{
string report = "";
string baseAttackerVar = BASE_TARGET_DUMMY_VAR+"."+player;
if ( utils.hasScriptVarTree(controller, baseAttackerVar) )
{
deltadictionary vars = controller.getScriptVars();
resizeable string[] attackTypes = new string[];
Enumeration keys = vars.keys();
while ( keys.hasMoreElements() )
{
string key = (string)(keys.nextElement());
if ( key.startsWith(baseAttackerVar + ".") )
{
string[] data = split(key, '.');
// data[0] = target_dummy
// data[1] = player obj_id
// data[2] = attack type
string attackType = data[2];
if ( !attackType.equals(LAST_ATTACK_TIME_VAR) )
{
utils.addElement(attackTypes, attackType);
}
}
}
report = utils.packStringId(REPORT_TITLE_SID) + addLineBreaks(1);
for ( int i = 0; i < attackTypes.length; i++ )
{
string attackTypeName = attackTypes[i];
string attackTypeVarName = baseAttackerVar+"."+attackTypeName;
int[] attackData = utils.getIntArrayScriptVar(controller, attackTypeVarName);
report += attackTypeName + ": { ";
for ( int j = 0; j < attackData.length; j++ )
{
report += attackData[j];
if ( j == attackData.length - 1 )
{
report += " }" + sui.newLine();
}
else
{
report += ", ";
}
}
}
}
else
{
report = utils.packStringId(new string_id("target_dummy", "placement_no_combat_data"));
}
if ( utils.hasScriptVar(player, "target_dummy.rawCombatReportSui") )
{
int oldPid = utils.getIntScriptVar(player, "target_dummy.rawCombatReportSui");
forceCloseSUIPage(oldPid);
}
// Create the dialog page.
int pid = sui.createSUIPage(sui.SUI_MSGBOX, controller, player, "noRawCombatDataTargetDummyHandler");
// Add elements text.
setSUIProperty(pid, sui.MSGBOX_TITLE, sui.PROP_TEXT, utils.packStringId(new string_id("target_dummy", "report_title")) );
setSUIProperty(pid, sui.MSGBOX_PROMPT, sui.PROP_TEXT, report);
// Add buttons.
sui.msgboxButtonSetup(pid, sui.YES_NO);
setSUIProperty(pid, sui.MSGBOX_BTN_OK, sui.PROP_TEXT, utils.packStringId(new string_id("target_dummy", "report_refreshbutton")));
setSUIProperty(pid, sui.MSGBOX_BTN_CANCEL, sui.PROP_TEXT, utils.packStringId(new string_id("target_dummy", "report_closebutton")));
// Show dialog.
utils.setScriptVar(player, "target_dummy.rawCombatReportSui", pid);
sui.showSUIPage(pid);
}
return;
}
float getPercentage(float num, float total)
{
float answer = num*10000/total;
int truncated = (int)answer;
return (float)truncated/100;
}
void removeCombatAi(obj_id targetDummy)
{
removeTriggerVolume(ai_lib.ALERT_VOLUME_NAME);
removeTriggerVolume(ai_lib.AGGRO_VOLUME_NAME);
if ( hasScript(targetDummy, "ai.creature_combat") )
{
detachScript(targetDummy, "ai.creature_combat");
}
return;
}
void freezeMob(obj_id targetDummy)
{
ai_lib.setDefaultCalmBehavior(targetDummy, ai_lib.BEHAVIOR_SENTINEL);
ai_lib.aiStopFollowing(targetDummy);
//setState(targetDummy, STATE_FROZEN, true);
}
void setFullHealth(obj_id targetDummy)
{
int maxHealth = getUnmodifiedMaxAttrib(targetDummy, HEALTH);
setAttrib(targetDummy, HEALTH, maxHealth);
}
void endTargetDummyCombat(obj_id targetDummy, obj_id player)
{
if(ai_lib.isInCombat(targetDummy) || ai_lib.isInCombat(player))
{
obj_id[] enemies = getHateList(targetDummy);
setCombatTarget(targetDummy, obj_id.NULL_ID);
stopCombat(targetDummy);
ai_lib.clearCombatData();
utils.removeScriptVarTree(targetDummy,"ai.combat");
setFullHealth(targetDummy);
removeAttackerFromCombat(targetDummy, player);
if ( enemies != null && enemies.length > 0 )
{
for ( int i=0; i < enemies.length; i++ )
{
obj_id enemy = enemies[i];
if ( isIdValid(enemy) && enemy != player )
{
removeAttackerFromCombat(targetDummy, enemy);
}
}
}
location where = getLocation(targetDummy);
if(where == null)
return;
obj_id controller = getObjIdObjVar(targetDummy, TARGET_DUMMY_CONTROLLER_OBJVAR);
if(!isValidId(controller))
return;
if(isValidId(createTargetDummyAtLocation(controller, player, where)))
destroyObject(targetDummy);
}
return;
}
void removeAttackerFromCombat(obj_id targetDummy, obj_id player)
{
removeHateTarget(targetDummy, player);
removeHateTarget(player, targetDummy);
stopCombat(player);
return;
}
void enterIntoCombat(obj_id targetDummy, obj_id player)
{
//debugSpeakMsg(targetDummy, "enterIntoCombat called...forced into combat.");
startCombat(targetDummy, player);
addHate(targetDummy, player, 1000.0f);
//startCombatWithAssist(targetDummy, player);
return;
}
/*************************************************************************/
/*** EXTRAS ***/
const string DATA = "datatables/tcg/target_dummy_extras.iff";
const string TYPE_COLUMN = "target_dummy_type";
const string RANDON_ANIM_COLUMN = "random_anims";
const string TRICK_ANIM_COLUMN = "trick_anims";
const string TARGET_DUMMY_LAST_EXTRAS_ANIM = "targetDummyLastAnim";
const string[] EXTRA_TYPES = {
RANDON_ANIM_COLUMN,
TRICK_ANIM_COLUMN
};
boolean hasTargetDummyExtras(obj_id targetDummy)
{
for ( int i = 0; i < EXTRA_TYPES.length; i++ )
{
string testExtra = getTargetDummyAnim(targetDummy, EXTRA_TYPES[i]);
if ( testExtra != null && testExtra.length() > 0 )
{
return true;
}
}
return false;
}
boolean hasTargetDummyRandomAnim(obj_id targetDummy)
{
string testAnim = getTargetDummyAnim(targetDummy, RANDON_ANIM_COLUMN);
if ( testAnim != null && testAnim.length() > 0 )
{
return true;
}
return false;
}
boolean hasTargetDummyTrickAnim(obj_id targetDummy)
{
string testTrick = getTargetDummyAnim(targetDummy, TRICK_ANIM_COLUMN);
if ( testTrick != null && testTrick.length() > 0 )
{
return true;
}
return false;
}
void doTargetDummyRandomAnim(obj_id targetDummy)
{
string animName = getTargetDummyAnim(targetDummy, RANDON_ANIM_COLUMN);
doTargetDummyAnimation(targetDummy, animName);
return;
}
void doTargetDummyTrick(obj_id targetDummy)
{
string trickName = getTargetDummyAnim(targetDummy, TRICK_ANIM_COLUMN);
doTargetDummyAnimation(targetDummy, trickName);
return;
}
string getTargetDummyAnim(obj_id targetDummy, string column)
{
string anims = getTargetDummyExtrasData(targetDummy, column);
if ( anims != null && anims.length() > 0 )
{
string[] animsList = split(anims, ',');
if ( animsList != null && animsList.length > 0 )
{
int randAnim = rand(0, animsList.length-1);
return animsList[randAnim];
}
}
return "";
}
void doTargetDummyAnimation(obj_id targetDummy, string animName)
{
if ( animName != null && animName.length() > 0 )
{
doAnimationAction(targetDummy, animName);
setObjVar(targetDummy, TARGET_DUMMY_LAST_EXTRAS_ANIM, animName);
}
return;
}
string getTargetDummyExtrasData(obj_id targetDummy, string column)
{
string result = "";
string type = getCreatureName(targetDummy);
if ( type != null && type.length() > 0 )
{
dictionary targetDummyExtras = dataTableGetRow(DATA, type);
if ( targetDummyExtras != null && !targetDummyExtras.isEmpty() )
{
result = targetDummyExtras.getString(column);
}
}
return result;
}
/*************************************************************************/
boolean blog(string msg)
{
if(msg == null || msg.equals(""))
return false;
if(LOGGING_ON)
LOG(TERMINAL_LOGGING, msg);
return true;
}