mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-07-29 23:15:55 -04:00
1410 lines
45 KiB
Plaintext
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;
|
|
}
|
|
|