include ai.ai_combat; include library.ai_lib; include library.quests; include library.create; include library.groundquests; include library.locations; include library.prose; include library.utils; // --------------------------------------------------------------------- inherits quest.task.ground.base_task; // --------------------------------------------------------------------- const string OBJVAR_DEFENSE_TARGET = "defend_target"; const string DEFEND_TARGET = "defendTarget"; const string QUEST_CRC = "questCrc"; const string TASK_ID = "taskId"; const string PLAYER = "player"; const string OBJVAR_BEEN_WARNED_DISTANCE = "beenWarned"; const string TASK_TYPE = "defend"; const string DOT = "."; const float DEFEND_DISTANCE_TIME_CHECK = 10; const float MAX_ALLOWED_DISTANCE = 40; const float CLEANUP_TIME = 120; const boolean LOGGING_ON = false; const string LOG_CAT = "defense_ground_task"; // --------------------------------------------------------------------- //fires when this task is added to the player trigger OnTaskActivated(int questCrc, int taskId) { blog("OnTaskActivated init"); groundquests.questOutputDebugInfo(self, questCrc, taskId, TASK_TYPE, "OnTaskActivated", TASK_TYPE + " task activated."); string baseObjVar = groundquests.setBaseObjVar(self, TASK_TYPE, questGetQuestName(questCrc), taskId); blog("baseObjVar: "+baseObjVar); //check the player for the OID of the defense object if(!hasObjVar(self, OBJVAR_DEFENSE_TARGET)) { return SCRIPT_CONTINUE; } blog("has var"); obj_id defendTarget = getObjIdObjVar(self, OBJVAR_DEFENSE_TARGET); if(!isValidId(defendTarget) || !exists(defendTarget)) { //fail quest questFailTask(questCrc, taskId, self); } blog("defendTarget: "+defendTarget); groundquests.addDestroyNotification(defendTarget, self); setObjVar(self, baseObjVar + DOT + OBJVAR_DEFENSE_TARGET, defendTarget); removeObjVar(self, OBJVAR_DEFENSE_TARGET); //set up first distance check pulse dictionary distanceCheckParams = new dictionary(); distanceCheckParams.put(PLAYER, self); distanceCheckParams.put(DEFEND_TARGET, defendTarget); distanceCheckParams.put(QUEST_CRC, questCrc); distanceCheckParams.put(TASK_ID, taskId); messageTo(self, "messageDefendCheckDistance", distanceCheckParams, DEFEND_DISTANCE_TIME_CHECK, false); return SCRIPT_CONTINUE; } // --------------------------------------------------------------------- messageHandler destroyNotification() { blog("destroyNotification init"); if(params == null) { blog("destroyNotification params null"); return SCRIPT_CONTINUE; } if(!params.containsKey("source")) { blog("destroyNotification params source NULL"); return SCRIPT_CONTINUE; } obj_id source = params.getObjId("source"); //blog("destroyNotification source: "+source); //get the base objvar for quests, all data is under that string taskObjVarName = groundquests.getTaskTypeObjVar(self, TASK_TYPE); if(taskObjVarName == null || taskObjVarName.length() <= 0) { return SCRIPT_CONTINUE; } blog("destroyNotification taskObjVarName: "+taskObjVarName); //get the list of quests obj_var_list questList = getObjVarList(self, taskObjVarName); if(questList == null) { return SCRIPT_CONTINUE; } blog("destroyNotification questList: "+questList); int countQuests = questList.getNumItems(); blog("destroyNotification countQuests: "+countQuests); //for each quest, check each task for(int i = 0; i < countQuests; ++i) { obj_var ov = questList.getObjVar(i); string questName = ov.getName(); int questCrc = questGetQuestId(questName); String questObjVarName = taskObjVarName + DOT + questName; if(hasObjVar(self, questObjVarName)) { //get the list of tasks for this quest that are of the right TASK_TYPE obj_var_list taskList = getObjVarList(self, questObjVarName); if(taskList != null) { int countTasks = taskList.getNumItems(); for (int j = 0; j < countTasks; ++j) { obj_var ov2 = taskList.getObjVar(j); string taskName = ov2.getName(); int taskId = utils.stringToInt(taskName); //check the data specific to this task type string escortTargetObjVarName = questObjVarName + DOT + taskName + DOT + OBJVAR_DEFENSE_TARGET; blog("destroyNotification escortTargetObjVarName: "+escortTargetObjVarName); if(hasObjVar(self, escortTargetObjVarName)) { obj_id escortTarget = getObjIdObjVar(self, escortTargetObjVarName); if(source == escortTarget) { questFailTask(questCrc, taskId, self); } else if(!exists(source) && !exists(escortTarget)) { questFailTask(questCrc, taskId, self); } } } } } } return SCRIPT_CONTINUE; } // --------------------------------------------------------------------- messageHandler messageDefendCheckDistance() { blog("messageDefendCheckDistance init"); if(params == null) { return SCRIPT_CONTINUE; } if(!params.containsKey(PLAYER)) { return SCRIPT_CONTINUE; } if(!params.containsKey(DEFEND_TARGET)) { return SCRIPT_CONTINUE; } if(!params.containsKey(QUEST_CRC)) { return SCRIPT_CONTINUE; } if(!params.containsKey(TASK_ID)) { return SCRIPT_CONTINUE; } blog("messageDefendCheckDistance contains all keys needed"); obj_id player = params.getObjId(PLAYER); obj_id defendTarget = params.getObjId(DEFEND_TARGET); int questCrc = params.getInt (QUEST_CRC); int taskId = params.getInt (TASK_ID); if(questIsTaskActive(questCrc, taskId, player)) { blog("messageDefendCheckDistance questIsTaskActive == true"); string baseObjVar = groundquests.getBaseObjVar(player, TASK_TYPE, questGetQuestName(questCrc), taskId); blog("messageDefendCheckDistance baseObjVar: "+baseObjVar); if(isDefenseObjectNearby(questCrc, taskId, player, defendTarget)) { blog("messageDefendCheckDistance isDefenseObjectNearby == true"); if(hasObjVar(player, baseObjVar + OBJVAR_BEEN_WARNED_DISTANCE)) removeObjVar(player, baseObjVar + OBJVAR_BEEN_WARNED_DISTANCE); } else { blog("messageDefendCheckDistance isDefenseObjectNearby == FALSE"); if(hasObjVar(self, baseObjVar + DOT + OBJVAR_DEFENSE_TARGET)) { obj_id defendTargetVar = getObjIdObjVar(self, baseObjVar + DOT + OBJVAR_DEFENSE_TARGET); if(defendTargetVar != defendTarget) { //unneeded check on old object blog("messageDefendCheckDistance defendTargetVar is NOT the correct object."); return SCRIPT_CONTINUE; } blog("messageDefendCheckDistance defendTargetVar is the correct object."); blog("messageDefendCheckDistance defendTargetVar: "+defendTargetVar); } failDefenseDistanceCheck(player, questCrc, taskId, defendTarget); } //send message for next pulse //this is not an infinite loop because it checks distance each time, and fails the task if the distance check fails twice in a row messageTo(self, "messageDefendCheckDistance", params, DEFEND_DISTANCE_TIME_CHECK, false); } return SCRIPT_CONTINUE; } // --------------------------------------------------------------------- boolean isDefenseObjectNearby(int questCrc, int taskId, obj_id player, obj_id defendTarget) { blog("isDefenseObjectNearby init"); boolean result = false; if(isIdValid(player) && isIdValid(defendTarget)) { blog("isDefenseObjectNearby player and defendTarget are VALID"); float distance = getDistance(player, defendTarget); if(distance < 0.0f) { return result; } result = distance <= MAX_ALLOWED_DISTANCE; blog("isDefenseObjectNearby DISTANCE: "+getDistance(player, defendTarget)); } blog("isDefenseObjectNearby result: "+result); return result; } // --------------------------------------------------------------------- void failDefenseDistanceCheck(obj_id player, int questCrc, int taskId, obj_id defenseTarget) { blog("failDefenseDistanceCheck init"); String baseObjVar = groundquests.getBaseObjVar(player, TASK_TYPE, questGetQuestName(questCrc), taskId); if(!hasObjVar(player, baseObjVar + OBJVAR_BEEN_WARNED_DISTANCE)) { //set objvar and warn player setObjVar(player, baseObjVar + OBJVAR_BEEN_WARNED_DISTANCE, "true"); string_id message = new string_id ("quest/groundquests", "static_defense_distance_warning"); prose_package pp = prose.getPackage(message, player, player, 0); prose.setDF(pp, DEFEND_DISTANCE_TIME_CHECK); sendSystemMessageProse(player, pp); } else { string_id message = new string_id ("quest/groundquests", "static_defense_failed_due_to_distance"); prose_package pp = prose.getPackage(message, player, player, 0); sendSystemMessageProse(player, pp); questFailTask(questCrc, taskId, player); } } // --------------------------------------------------------------------- //fires when the task is completed trigger OnTaskCompleted(int questCrc, int taskId) { blog("OnTaskCompleted init"); groundquests.questOutputDebugInfo(self, questCrc, taskId, TASK_TYPE, "OnTaskCompleted", TASK_TYPE + " task completed."); String baseObjVar = groundquests.getBaseObjVar(self, TASK_TYPE, questGetQuestName(questCrc), taskId); obj_id escort = getObjIdObjVar(self, baseObjVar + DOT + OBJVAR_DEFENSE_TARGET); if(hasObjVar(escort, "questCallBack")) { dictionary webster = new dictionary(); webster.put("questComplete", true); webster.put("player", self); messageTo(escort, "handleQuestCallBack", webster, 0, false); } cleanup(self, questCrc, taskId); return SCRIPT_CONTINUE; } // --------------------------------------------------------------------- //fires when the task is failed trigger OnTaskFailed(int questCrc, int taskId) { blog("OnTaskFailed init"); groundquests.questOutputDebugInfo(self, questCrc, taskId, TASK_TYPE, "OnTaskFailed", TASK_TYPE + " task failed."); String baseObjVar = groundquests.getBaseObjVar(self, TASK_TYPE, questGetQuestName(questCrc), taskId); obj_id escort = getObjIdObjVar(self, baseObjVar + DOT + OBJVAR_DEFENSE_TARGET); if(hasObjVar(escort, "questCallBack")) { dictionary webster = new dictionary(); webster.put("questComplete", false); webster.put("player", self); messageTo(escort, "handleQuestCallBack", webster, 0, false); } cleanup(self, questCrc, taskId); return SCRIPT_CONTINUE; } // --------------------------------------------------------------------- //fires when the task is cleared trigger OnTaskCleared(int questCrc, int taskId) { blog("OnTaskCleared init"); groundquests.questOutputDebugInfo(self, questCrc, taskId, TASK_TYPE, "OnTaskCleared", TASK_TYPE + " task cleared."); String baseObjVar = groundquests.getBaseObjVar(self, TASK_TYPE, questGetQuestName(questCrc), taskId); obj_id escort = getObjIdObjVar(self, baseObjVar + DOT + OBJVAR_DEFENSE_TARGET); if(hasObjVar(escort, "questCallBack")) { dictionary webster = new dictionary(); webster.put("questComplete", false); webster.put("player", self); messageTo(escort, "handleQuestCallBack", webster, 0, false); } cleanup(self, questCrc, taskId); return SCRIPT_CONTINUE; } // --------------------------------------------------------------------- void cleanup(obj_id player, int questCrc, int taskId) { blog("cleanup init"); // destroy the escort target String baseObjVar = groundquests.getBaseObjVar(player, TASK_TYPE, questGetQuestName(questCrc), taskId); String escortTargetObjVarName = baseObjVar + DOT + OBJVAR_DEFENSE_TARGET; obj_id escortTarget = getObjIdObjVar(player, escortTargetObjVarName); if (escortTarget != null) { removeObjVar(player, escortTargetObjVarName); if(!ai_lib.isAiDead(escortTarget)) { //cleanup live escort targets after 2 minutes dictionary params = new dictionary(); messageTo(escortTarget, "messageEscortCleanup", params, CLEANUP_TIME, false); ai_lib.aiStopFollowing(escortTarget); } } groundquests.clearBaseObjVar(player, TASK_TYPE, questGetQuestName(questCrc), taskId); } // --------------------------------------------------------------------- trigger OnLogout() { blog("OnLogout init"); groundquests.failAllActiveTasksOfType(self, TASK_TYPE); return SCRIPT_CONTINUE; } // --------------------------------------------------------------------- trigger OnInitialize() { blog("OnInitialize init"); groundquests.failAllActiveTasksOfType(self, TASK_TYPE); return SCRIPT_CONTINUE; } // --------------------------------------------------------------------- trigger OnDetach() { blog("OnDetach init"); //make sure the base objvar is removed removeObjVar(self, groundquests.getTaskTypeObjVar(self, TASK_TYPE)); return SCRIPT_CONTINUE; } // --------------------------------------------------------------------- void blog(string text) { if(LOGGING_ON) { LOG(LOG_CAT, text); } }