/********************************************************************** * Copyright (c)2000-2002 Sony Online Entertainment Inc. * All Rights Reserved * * Title: battlefield.scriptlib * Description: Library for battlefields * @author $Author:$ * @version $Revision:$ **********************************************************************/ /***** INCLUDES ********************************************************/ include library.factions; include library.player_structure; include library.pet_lib; include library.create; include library.utils; include java.lang.Math; /***** CONSTANTS *******************************************************/ const string BATTLEFIELD_DATATABLE = "datatables/battlefield/battlefield.iff"; const string BATTLEFIELD_MARKER_DATATABLE = "datatables/battlefield/marker.iff"; const string BUILDABLE_STRUCTURE_DATATABLE = "datatables/battlefield/buildable_structure.iff"; const string SPAWNER_DATATABLE = "datatables/battlefield/spawner.iff"; const string BATTLEFIELD_MARKER = "object/static/structure/tatooine/antenna_tatt_style_1.iff"; // Battlefield datatable const string DATATABLE_COL_NAME = "battlefield"; const string DATATABLE_COL_AREA = "area"; const string DATATABLE_COL_TYPE = "type"; const string DATATABLE_COL_X1 = "x1"; const string DATATABLE_COL_Y1 = "y1"; const string DATATABLE_COL_Z1 = "z1"; const string DATATABLE_COL_RADIUS = "radius"; const string DATATABLE_COL_GAME_TYPE = "gameType"; const string DATATABLE_COL_RESTART_MIN = "restartMin"; const string DATATABLE_COL_RESTART_MAX = "restartMax"; const string DATATABLE_COL_GAME_TIME = "gameTime"; const string DATATABLE_COL_IMPERIAL = "Imperial"; const string DATATABLE_COL_REBEL = "Rebel"; const string DATATABLE_COL_HUTT = "Hutt"; const string DATATABLE_COL_OBJECT = "object"; const string DATATABLE_COL_OBJECT_X = "object_x"; const string DATATABLE_COL_OBJECT_Y = "object_y"; const string DATATABLE_COL_OBJECT_Z = "object_z"; const string DATATABLE_COL_OBJECT_DELTA = "object_delta"; const string DATATABLE_COL_HEADING = "heading"; const string DATATABLE_COL_FACTION = "faction"; const string DATATABLE_COL_STRUCTURE_TYPE = "structure_type"; const string DATATABLE_COL_CRITICAL = "gameCritical"; const string DATATABLE_COL_VALUE1 = "value1"; const string DATATABLE_COL_VALUE2 = "value2"; const string DATATABLE_COL_SCRIPT = "script"; // Buildable structure const string DATATABLE_COL_BUILDING_NAME = "name"; const string DATATABLE_COL_TEMPLATE = "template"; const string DATATABLE_COL_BUILD_COST = "cost"; // Spawner data const string DATATABLE_COL_SPAWNER_TYPE = "type"; const string DATATABLE_COL_SPAWNER_PULSE = "pulse"; const string DATATABLE_COL_SPAWNER_MAX_SPAWN = "max_spawn"; const string DATATABLE_COL_SPAWNER_MAX_POPULATION = "max_population"; const string DATATABLE_COL_SPAWNER_TEMPLATE = "spawn_template"; const string DATATABLE_COL_SPAWNER_MIN_NUMBER = "min_number"; const string DATATABLE_COL_SPAWNER_MAX_NUMBER = "max_number"; const string DATATABLE_COL_SPAWNER_WEIGHT = "weight"; // Scripts const string SCRIPT_BATTLEFIELD_REGION = "systems.battlefield.battlefield_region"; const string SCRIPT_PLAYER_BATTLEFIELD = "systems.battlefield.player_battlefield"; const string SCRIPT_BATTLEFIELD_OBJECT = "systems.battlefield.battlefield_object"; const string SCRIPT_DESTRUCTIBLE_BUILDING = "systems.battlefield.destructible_building"; const string SCRIPT_DESTROY_OBJECTIVE = "systems.battlefield.destroy_objective"; const string SCRIPT_BATTLEFIELD_CONSTRUCTOR = "systems.battlefield.battlefield_constructor"; const string SCRIPT_BARRACKS = "systems.battlefield.barracks"; const string SCRIPT_BATTLEFIELD_SPAWNER = "systems.battlefield.battlefield_spawner"; const string SCRIPT_FACTION_ITEM = "npc.faction_recruiter.faction_item"; // objvars --- // Master object/region const string VAR_BATTLEFIELD = "battlefield"; const string VAR_NAME = "battlefield.name"; const string VAR_PLANET = "battlefield.planet"; const string VAR_VERSION = "battlefield.version"; const string VAR_MASTER_OBJECT = "battlefield.master_object"; const string VAR_EXTENT = "battlefield.extent"; const string VAR_MARKERS = "battlefield.markers"; const string VAR_RESTART_TIME_MIN = "battlefield.restart_time_min"; const string VAR_RESTART_TIME_MAX = "battlefield.restart_time_max"; const string VAR_GAME_DURATION = "battlefield.game_duration"; const string VAR_NEXT_GAME = "battlefield.next_game"; const string VAR_GAME_TYPE = "battlefield.game_type"; const string VAR_FACTIONS_ALLOWED = "battlefield.factions_allowed"; const string VAR_FACTIONS_AI_ALLOWED = "battlefield.factions_ai_allowed"; const string VAR_START_LOCATIONS = "battlefield.start_locations"; const string VAR_BASE_OBJECTS = "battlefield.base_objects"; const string VAR_PLAYERS_IN_BATTLEFIELD = "battlefield.player_in_battlefield"; const string VAR_WAYPOINTS = "battlefield.waypoints"; // Game variables const string VAR_GAME = "battlefield.game"; const string VAR_TIME_REMAINING = "battlefield.game.time_remaining"; const string VAR_PARTICIPANTS = "battlefield.game.participants"; const string VAR_FACTIONS_REMAINING = "battlefield.game.factions_remaining"; const string VAR_FACTIONS_AI_REMAINING = "battlefield.game.factions_ai_remaining"; const string VAR_BUILD_POINTS = "battlefield.game.build_points_"; const string VAR_KILLS = "battlefield.game.stats.kills_"; const string VAR_DEATHS = "battlefield.game.stats.deaths_"; // Previous game stat variables const string VAR_STAT_ROOT = "battlefield.stats"; const string VAR_STAT_TYPE = "battlefield.stats.type"; const string VAR_STAT_TIME = "battlefield.stats.time"; const string VAR_STAT_WINNER = "battlefield.stats.winner"; const string VAR_STAT_PLAYERS = "battlefield.stats.players"; const string VAR_STAT_KILLS = "battlefield.stats.kills_"; const string VAR_STAT_DEATHS = "battlefield.stats.deaths_"; // Player const string VAR_BATTLEFIELD_ENTERED = "battlefield.battlefield_entered"; const string VAR_BATTLEFIELD_TO_ENTER = "battlefield.battlefield_to_enter"; const string VAR_TEAM_FACTION = "battlefield.team_faction"; const string VAR_TIME_ENTERED = "battlefield.time_entered"; const string VAR_TIME_EXITED = "battlefield.time_exited"; const string VAR_CHATROOM_ALL = "battlefield.chatroom_all"; const string VAR_CHATROOM_FACTION = "battlefield.chatroom_faction"; const string VAR_EXPELLED = "battlefield.expelled"; const string VAR_SELECTING_FACTION = "battlefield.selecting_faction"; // Spawners const string VAR_SPAWNER_TYPE = "battlefield.spawner.type"; const string VAR_SPAWNER_PULSE = "battlefield.spawner.pulse"; const string VAR_SPAWNER_MAX = "battlefield.spawner.maximum_spawn"; const string VAR_SPAWNER_CURRENT = "battlefield.spawner.current_spawn"; const string VAR_SPAWNER_CURRENT_POPULATION = "battlefield.spawner.current_population"; const string VAR_SPAWNER_MAX_POPULATION = "battlefield.spawner.max_population"; const string VAR_SPAWNED_BY = "battlefield.spawned_by"; const string VAR_SPAWNED_BATTLEFIELD = "battlefield.spawned_battlefield"; // Game critical objects const string VAR_GAME_CRITICAL = "battlefield.game_critical"; const string VAR_VALUE1 = "battlefield.value1"; const string VAR_VALUE2 = "battlefield.value2"; const string VAR_COMBAT_DESTROYED = "battlefield.combat_destroyed"; // Construction sites/Player built const string VAR_BUILDTIME = "battlefield.buildtime"; const string VAR_TIMESTAMP = "battlefield.timestamp"; const string VAR_HEIGHT = "battlefield.height"; const string VAR_CONSTRUCTED = "battlefield.constructed"; const string VAR_REPAIRING = "battlefield.repairing"; const string VAR_REPAIR_COST = "battlefield.repair_cost"; const string VAR_LAST_BUILD = "battlefield.last_build"; const string VAR_BUILD_RATE = "battlefield.build_rate"; const string VAR_REINFORCEMENT_TEMPLATE = "battlefield.reinforcement_template"; const string VAR_REINFORCEMENT_NAME = "battlefield.reinforcement_name"; const string VAR_REINFORCEMENT_COST = "battlefield.reinforcement_cost"; // Misc const string VAR_DECLARED = "faction_recruiter.declared"; // system values const float MARKER_SPACING = 4.0f; const int GAME_TIME_PULSE = 5; const float OUTER_PERIMETER_WIDTH = 15.0f; const float MIN_START_LOCATION_TOLERANCE = 1.0f; const float MAX_START_LOCATION_TOLERANCE = 5.0f; const int CONFINEMENT_TIME = 0; const float DEATH_TIME = 15.0f; const int STARTING_BUILD_POINTS = 500; const float BUILD_POINT_RECHARGE_PULSE = 30.0f; const int BUILD_POINT_RECHARGE_AMOUNT = 10; const float CONSTRUCTOR_RANGE = 60.0f; const float REINFORCEMENT_RANGE = 10.0f; const float REPAIR_RANGE = 10.0f; const float REPAIR_PULSE = 5.0f; const int MAXIMUM_POPULATION = 50; const int MAXIMUM_FACTION_SIZE_DIFFERENCE = 5; // version const int CURRENT_VERSION = 3; // trigger names const string STRING_TRIG_BOUNDARY = "battlefield_boundary"; const string STRING_TRIG_OUTER_PERIMETER = "battlefield_outer_perimeter"; // misc const string GAME_SCRIPT_PATH = "systems.battlefield.game_"; /***** TRIGGERS ********************************************************/ /***** MESSAGEHANDLERS *************************************************/ /***** MESSAGEHANDLERS *************************************************/ /***** COMMANDHANDLERS *************************************************/ /***** FUNCTIONS *************************************************/ /*********************************************************************** * @brief Creates battlefields for the specified area * * @param string area * * @return void ***********************************************************************/ void createBattlefieldRegions(string area) { int numItems = dataTableGetNumRows(BATTLEFIELD_DATATABLE); int numMarkers = dataTableGetNumRows(BATTLEFIELD_MARKER_DATATABLE); for (int i = 0; i < numItems; i++) { dictionary row = dataTableGetRow(BATTLEFIELD_DATATABLE, i); string name = row.getString(DATATABLE_COL_NAME); string bf_area = row.getString(DATATABLE_COL_AREA); //LOG("LOG_CHANNEL", "name ->" + name + " bf_area ->" + bf_area); if (area == bf_area) { // Get the region's data string type = row.getString(DATATABLE_COL_TYPE); float x1 = row.getFloat(DATATABLE_COL_X1); float y1 = row.getFloat(DATATABLE_COL_Y1); float z1 = row.getFloat(DATATABLE_COL_Z1); float radius = row.getFloat(DATATABLE_COL_RADIUS); string game_type = row.getString(DATATABLE_COL_GAME_TYPE); int restart_min = row.getInt(DATATABLE_COL_RESTART_MIN); int restart_max = row.getInt(DATATABLE_COL_RESTART_MAX); int game_time = row.getInt(DATATABLE_COL_GAME_TIME); int imperial = row.getInt(DATATABLE_COL_IMPERIAL); int rebel = row.getInt(DATATABLE_COL_REBEL); int hutt = row.getInt(DATATABLE_COL_HUTT); LOG("LOG_CHANNEL", " type ->" + type + " " + x1 + "/" + y1 + "/" + z1 + "/" + radius); if (type == null) continue; // Check to see if a battlefield is already in the area. int regionPvpType; if ( type == "pvp" ) regionPvpType = regions.PVP_REGION_TYPE_BATTLEFIELD_PVP; else if (type == "pve") regionPvpType = regions.PVP_REGION_TYPE_BATTLEFIELD_PVE; else { LOG("LOG_CHANNEL", " Unsupported pvp type " + type + " read, skipping"); continue; } // Create the locations for the region's bounds location loc = new location(x1, y1, z1, bf_area); string regionName = "@battlefield:" + name; // Check to see if a battlefield is already in the area. if (getRegionsWithPvPAtPoint(loc, regionPvpType) != null) { LOG("LOG_CHANNEL", " " + type.toUpperCase() + " Battlefield found, skipping..."); } else { // get the geography at the battlefield int geography = regions.GEO_PLAINS; region testRegion = getSmallestRegionAtPoint(loc); if ( testRegion != null ) geography = testRegion.getGeographicalType(); // Create the region createCircleRegion(loc, radius, regionName, regionPvpType, regions.BUILD_TRUE, regions.MUNI_FALSE, geography, 0, 0, regions.SPAWN_FALSE, regions.MISSION_NONE, true, false); } // Create the battlefield marker string markerName = null; float bestRadius = 0.0f; for (int j = 0; j < numMarkers; ++j) { dictionary markerRow = dataTableGetRow(BATTLEFIELD_MARKER_DATATABLE, j); float markerRadius = markerRow.getFloat(DATATABLE_COL_RADIUS); if (Math.abs(markerRadius-radius) < Math.abs(bestRadius-radius)) { bestRadius = markerRadius; markerName = markerRow.getString(DATATABLE_COL_TEMPLATE); } } if (markerName != null) { obj_id marker = createObject(markerName, loc); if (isIdValid(marker)) { setBattlefieldMarkerRegionName(marker, regionName); if (exists(marker)) persistObject(marker); } } } } return; } void destroyBattlefieldRegions(string area) { if (area == null) return; int numItems = dataTableGetNumRows(BATTLEFIELD_DATATABLE); for (int i = 0; i < numItems; i++) { dictionary row = dataTableGetRow(BATTLEFIELD_DATATABLE, i); string name = row.getString(DATATABLE_COL_NAME); string bf_area = row.getString(DATATABLE_COL_AREA); string type = row.getString(DATATABLE_COL_TYPE); if (type == null || type.length() < 1) continue; if (bf_area != null && bf_area.length() > 0) { if (area == bf_area) { LOG("LOG_CHANNEL", "battlefield::destroyBattlefieldRegions -- " + name); float x1 = row.getFloat(DATATABLE_COL_X1); float y1 = row.getFloat(DATATABLE_COL_Y1); float z1 = row.getFloat(DATATABLE_COL_Z1); location loc = new location(x1, y1, z1, bf_area); int regionPvpType; if ( type == "pvp" ) regionPvpType = regions.PVP_REGION_TYPE_BATTLEFIELD_PVP; else if (type == "pve") regionPvpType = regions.PVP_REGION_TYPE_BATTLEFIELD_PVE; else { LOG("LOG_CHANNEL", " Unsupported pvp type " + type + " read, skipping"); continue; } region[] regs = getRegionsWithPvPAtPoint(loc, regionPvpType); if (regs != null && regs.length > 0) { for (int j = 0; j < regs.length; j++) { obj_id bf_object = getMasterObjectFromRegion(regs[j]); if (isIdValid(bf_object)) destroyBattlefield(bf_object); } } } } } } /*********************************************************************** * @brief Updates a battlefield's object values from the datatable. * * @param obj_id master_object * * @return boolean false on fail ***********************************************************************/ boolean updateBattlefieldData(obj_id master_object, region bf) { LOG("LOG_CHANNEL", "battlefield::updateBattlefield"); if (master_object == null || master_object == obj_id.NULL_ID) { LOG("LOG_CHANNEL", "battlefield.updateBattlefield -- the battlefield object is null."); debugServerConsoleMsg(null, "battlefield.updateBattlefield -- the battlefield object is null."); return false; } if (bf == null) { bf = getBattlefield(master_object); if (bf == null) { LOG("LOG_CHANNEL", "battlefield.updateBattlefield -- the region is null."); debugServerConsoleMsg(null, "battlefield.updateBattlefield -- the region is null."); return false; } } string name = getBattlefieldName(bf); int idx = dataTableSearchColumnForString(name, DATATABLE_COL_NAME, BATTLEFIELD_DATATABLE); if (idx == -1) { LOG("LOG_CHANNEL", "battlefield::getSpawnerData -- unable to find an entry for " + name); debugServerConsoleMsg(null, "battlefield::getSpawnerData -- unable to find an entry for " + name); return false; } // Get the data from the datatable dictionary row = dataTableGetRow(BATTLEFIELD_DATATABLE, idx); string type = row.getString(DATATABLE_COL_TYPE); float x1 = row.getFloat(DATATABLE_COL_X1); float y1 = row.getFloat(DATATABLE_COL_Y1); float z1 = row.getFloat(DATATABLE_COL_Z1); float radius = row.getFloat(DATATABLE_COL_RADIUS); string game_type = row.getString(DATATABLE_COL_GAME_TYPE); int restart_min = row.getInt(DATATABLE_COL_RESTART_MIN); int restart_max = row.getInt(DATATABLE_COL_RESTART_MAX); int game_time = row.getInt(DATATABLE_COL_GAME_TIME); int imperial = row.getInt(DATATABLE_COL_IMPERIAL); int rebel = row.getInt(DATATABLE_COL_REBEL); int hutt = row.getInt(DATATABLE_COL_HUTT); // Set the battlefield type // if (type.toUpperCase().equals("PVP")) // setRegionPvP(bf, regions.PVP_REGION_TYPE_BATTLEFIELD_PVP); // else // setRegionPvP(bf, regions.PVP_REGION_TYPE_BATTLEFIELD_PVE); // Set the objvars setObjVar(master_object, VAR_NAME, bf.getName()); setObjVar(master_object, VAR_PLANET, bf.getPlanetName()); setObjVar(master_object, VAR_EXTENT, radius); setObjVar(master_object, VAR_GAME_TYPE, game_type); setObjVar(master_object, VAR_RESTART_TIME_MIN, restart_min); setObjVar(master_object, VAR_RESTART_TIME_MAX, restart_max); setObjVar(master_object, VAR_GAME_DURATION, game_time); // Set factions allowed resizeable string[] factions_allowed = new string[0]; resizeable string[] factions_ai = new string[0]; LOG("LOG_CHANNEL", "imperial ->" + imperial + " rebel ->" + rebel); // 1 enables a faction for players and ai. // 2 enables a faction for just ai. if (imperial == 1) factions_allowed = utils.addElement(factions_allowed, factions.FACTION_IMPERIAL); else if (imperial == 2) factions_ai = utils.addElement(factions_ai, factions.FACTION_IMPERIAL); if (rebel == 1) factions_allowed = utils.addElement(factions_allowed, factions.FACTION_REBEL); else if (rebel == 2) factions_ai = utils.addElement(factions_ai, factions.FACTION_REBEL); if (hutt == 1) factions_allowed = utils.addElement(factions_allowed, factions.FACTION_HUTT); else if (hutt == 2) factions_ai = utils.addElement(factions_ai, factions.FACTION_HUTT); if (factions_allowed.length > 0) { // Set Factions allowed and create a starting location array with as many elements setObjVar(master_object, VAR_FACTIONS_ALLOWED, factions_allowed); location[] start_locations = new location[factions_allowed.length]; if(start_locations.length > 0) { // Zero length array check, should be redundant setObjVar(master_object, VAR_START_LOCATIONS, start_locations); } } else { LOG("LOG_CHANNEL", "battlefield::updateBattlefield -- there are no allowed factions for " + master_object); return false; } if (factions_ai.length > 0) setObjVar(master_object, VAR_FACTIONS_AI_ALLOWED, factions_ai); setObjVar(master_object, VAR_VERSION, CURRENT_VERSION); return true; } /*********************************************************************** * @brief Surrounds a battlefield with markers * * @param obj_id master_object * * @return boolean ***********************************************************************/ boolean markBattlefield(region r) { if (r == null) return false; // For now we only use circular battlefields. // Make the radius of the markers slightly larger than the trigger volume so that they // stay out of it. float radius = getBattlefieldExtent(r) + 2.0f; location bf_loc = getBattlefieldLocation(r); // The amount of markers to drop is dependant on the radius. float degree_incr = 360.0f * MARKER_SPACING / radius; if (degree_incr > 90) degree_incr = 90; //LOG("LOG_CHANNEL", "degree_incr ->" + degree_incr); float radian_incr = (float)Math.toRadians(degree_incr); resizeable obj_id[] markers = new obj_id[0]; for (float angle = 0.0f; angle < 2 * Math.PI; angle = angle + radian_incr) { float x = radius * (float)Math.sin(angle) + bf_loc.x; float z = radius * (float)Math.cos(angle) + bf_loc.z; float y = getHeightAtLocation(x, z); //LOG("LOG_CHANNEL", "angle ->" + angle + " " + x + "/" + y + "/" + z); location loc = new location(x, y, z, getCurrentSceneName()); obj_id marker = createObject(BATTLEFIELD_MARKER, loc); persistObject(marker); markers = utils.addElement(markers, marker); } // Keep track of the markers on the master object so that they may be cleaned up obj_id master_object = getMasterObjectFromRegion(r); if(markers.length > 0) { // Zero length array check setObjVar(master_object, VAR_MARKERS, markers); } return true; } /*********************************************************************** * @brief Returns the battlefield at the given locaiton * * @param location loc * * @return region; returns null if the location is not in a battlefield ***********************************************************************/ region getBattlefield(location loc) { // Check for PvP battlefields region[] rPvP = getRegionsWithPvPAtPoint(loc, regions.PVP_REGION_TYPE_BATTLEFIELD_PVP); if (rPvP != null) { // There should only be one battlefield at a given point return rPvP[0]; } else { // Check for PvE battlefields region[] rPvE = getRegionsWithPvPAtPoint(loc, regions.PVP_REGION_TYPE_BATTLEFIELD_PVE); if (rPvE != null) { // There should only be one battlefield at a given point return rPvE[0]; } } return null; } /*********************************************************************** * @brief Overload for getBattlefield * * @param obj_id object * * @return region; returns null if the object is not in a battlefield ***********************************************************************/ region getBattlefield(obj_id object) { if (object == null || object == obj_id.NULL_ID) return null; location loc = getLocation(object); return getBattlefield(loc); } /*********************************************************************** * @brief Determines whether or not the battle field is PvP. * * @param region r * * @return boolean ***********************************************************************/ boolean isBattlefieldPvP(region r) { if (r == null) return false; int pvpType = r.getPvPType(); if (pvpType == regions.PVP_REGION_TYPE_BATTLEFIELD_PVP) return true; else return false; } /*********************************************************************** * @brief Determines whether or not the battle field is PvE. * * @param region r * * @return boolean ***********************************************************************/ boolean isBattlefieldPvE(region r) { if (r == null) return false; int pvpType = r.getPvPType(); if (pvpType == regions.PVP_REGION_TYPE_BATTLEFIELD_PVE) return true; else return false; } /*********************************************************************** * @brief Determines whether or not a the battlefield is active * * @param obj_id master_object * * @return boolean ***********************************************************************/ boolean isBattlefieldActive(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return false; int time = getGameTimeRemaining(master_object); if (time == -1) return false; else return true; } /*********************************************************************** * @brief Overload for isBattlefieldActive * * @param region r battlefield to test * * @return boolean ***********************************************************************/ boolean isBattlefieldActive(region r) { if (r == null) return false; obj_id master_object = getMasterObjectFromRegion(r); return isBattlefieldActive(master_object); } /*********************************************************************** * @brief Determines whether or not a player is on a given team * * @param obj_id player * @param string faction * @param obj_id master_object * * @return boolean ***********************************************************************/ boolean isFactionTeamMember(obj_id player, string faction, obj_id master_object) { if (player == null || player == obj_id.NULL_ID) return false; if (master_object == null || master_object == obj_id.NULL_ID) return false; obj_id[] faction_team = getFactionTeam(master_object, faction); if (faction_team != null) { for (int i = 0; i < faction_team.length; i++) { if (player == faction_team[i]) return true; } } return false; } /*********************************************************************** * @brief Determines whether or not a player faction is allowed in * the game. * * @param obj_id master_object * @param string faction * * @return boolean ***********************************************************************/ boolean isFactionAllowed(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (faction == null) return false; string[] factions_allowed = getFactionsAllowed(master_object); if (factions_allowed == null) return false; int idx = utils.getElementPositionInArray(factions_allowed, faction); if (idx == -1) return false; else return true; } /*********************************************************************** * @brief Determines whether or not a faction is still remaining in * the game. * * @param obj_id master_object * @param string faction * * @return boolean ***********************************************************************/ boolean isFactionRemaining(obj_id master_object, string faction) { LOG("LOG_CHANNEL", "battlefield::isFactionRemaining -- " + master_object + " " + faction); if (master_object == null || master_object == obj_id.NULL_ID) return false; if (!isBattlefieldActive(master_object)) return false; if (!hasObjVar(master_object, VAR_FACTIONS_REMAINING)) return false; else { string[] factions_remaining = getFactionsRemaining(master_object); int idx = utils.getElementPositionInArray(factions_remaining, faction); //LOG("LOG_CHANNEL", "battlefield::isFactionRemaining -- " + idx); if (idx == -1) return false; else return true; } } /*********************************************************************** * @brief Determines whether or not a faction is a player faction. * * @param obj_id master_object * @param string faction * * @return boolean ***********************************************************************/ boolean isPlayerFaction(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return false; string[] factions_allowed = getFactionsAllowed(master_object); if (factions_allowed != null) { int idx = utils.getElementPositionInArray(factions_allowed, faction); if (idx != -1) { LOG("LOG_CHANNEL", "battlefield::isPlayerFaction -- true"); return true; } else { LOG("LOG_CHANNEL", "battlefield::isPlayerFaction -- false"); return false; } } else { LOG("LOG_CHANNEL", "battlefield::isPlayerFaction -- factions_allowed is null."); return false; } } /*********************************************************************** * @brief Determines whether or not a faction is an ai faction. * * @param obj_id master_object * @param string faction * * @return boolean ***********************************************************************/ boolean isAIFaction(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return false; string[] ai_factions = getAIFactionsAllowed(master_object); if (ai_factions != null) { int idx = utils.getElementPositionInArray(ai_factions, faction); if (idx != -1) return true; else return false; } else { LOG("LOG_CHANNEL", "battlefield::isAIFaction -- ai_factions is null."); return false; } } /*********************************************************************** * @brief Determines whether or not a player has an existing * select faction sui. * * @param obj_id player * * @return boolean ***********************************************************************/ boolean hasSelectFactionSui(obj_id player) { if (!isIdValid(player)) { LOG("LOG_CHANNEL", "battlefield::hasSelectFactionSui -- " + player + " (false)"); return false; } if (utils.hasScriptVar(player, VAR_SELECTING_FACTION)) { LOG("LOG_CHANNEL", "battlefield::hasSelectFactionSui -- " + player + " (true)"); return true; } else { LOG("LOG_CHANNEL", "battlefield::hasSelectFactionSui -- " + player + " (false)"); return false; } } /*********************************************************************** * @brief Determines whether or not a player may join a given faction. * * @param obj_id master_object * @param obj_id param * @param string faction * * @return boolean ***********************************************************************/ boolean canJoinFaction(obj_id master_object, obj_id player, string faction) { LOG("LOG_CHANNEL", "battlefield.canJoinFaction -- " + master_object + "/" + player + "/" + faction); if (master_object == null || master_object == obj_id.NULL_ID) return false; string[] factions_allowed = getFactionsAllowed(master_object); int total_population = 0; obj_id[] players = getParticipantsOnBattlefield(master_object); if (players != null) total_population = players.length; // if the total population exceeds the battlefield limits, can't join any faction. if (total_population >= MAXIMUM_POPULATION) { LOG("LOG_CHANNEL", player + " ->There are too many combatants currently within the battlefield."); sendSystemMessageTestingOnly(player, "There are too many combatants currently within the battlefield."); return false; } // Check the count in each faction. resizeable int[] factions_allowed_sizes = new int[0]; int number_factions = factions_allowed.length; int faction_size = 0; if (factions_allowed != null) { for (int i = 0; i < factions_allowed.length; i++) { obj_id[] faction_team = getFactionTeam(master_object, factions_allowed[i]); int size; if (faction_team != null) size = faction_team.length; else size = 0; factions_allowed_sizes = utils.addElement(factions_allowed_sizes, size); if (factions_allowed[i].equals(faction)) faction_size = size; } } else { LOG("LOG_CHANNEL", "battlefield.canJoinFaction -- factions_allowed is null for " + master_object); return false; } // The faction to join can not have more than its faction of the maximum population int max_faction_pop = MAXIMUM_POPULATION / number_factions; if (faction_size >= max_faction_pop) { LOG("LOG_CHANNEL", player + " ->There are too many combantants on the " + faction + " faction to join at this list."); sendSystemMessageTestingOnly(player, "There are too many combantants on the " + faction + " faction to join at this list."); return false; } // Compare the sizes of the factions. No faction may have more than 10 for (int i = 0; i < factions_allowed_sizes.length; i++) { if (!factions_allowed[i].equals(faction)) { if (faction_size - factions_allowed_sizes[i] > MAXIMUM_FACTION_SIZE_DIFFERENCE) { LOG("LOG_CHANNEL", player + " ->There are too many combantants on the " + faction + " faction to join at this list."); sendSystemMessageTestingOnly(player, "There are too many combantants on the " + faction + " faction to join at this list."); return false; } } } return true; } /*********************************************************************** * @brief Determines whether or not a location is near a battlefield * constructor of the specified faction * * @param obj_id master_object * @param location loc * @param string faction * * @return boolean ***********************************************************************/ boolean isNearBattlefieldConstructor(obj_id master_object, location loc, string faction) { if (loc.y == 0.0f) { // We need a y coordinate for an accurate range check. Since the placement tool // does not give y, we must set it outselves. loc.y = getElevation(loc); } obj_id[] objects = getObjectsInRange(loc, CONSTRUCTOR_RANGE); if (objects != null) { for (int i = 0; i < objects.length; i++) { //LOG("LOG_CHANNEL", "object ->" + objects[i]); if (hasScript(objects[i], SCRIPT_BATTLEFIELD_CONSTRUCTOR)) { region bf = getRegionFromMasterObject(master_object); int obj_faction_id = pvpBattlefieldGetFaction(objects[i], bf); string obj_faction = factions.getFactionNameByHashCode(obj_faction_id); //LOG("LOG_CHANNEL", "... faction ->" + faction + " obj_faction ->" + obj_faction); if (faction.equals(obj_faction)) { LOG("LOG_CHANNEL", "constructor ->" + objects[i]); return true; } } } } return false; } /*********************************************************************** * @brief Determines whether or not an object was battlefield constructed * * @param obj_id object * * @return boolean ***********************************************************************/ boolean isBattlefieldConstructed(obj_id object) { if (object == null || object == obj_id.NULL_ID) return false; if (hasObjVar(object, VAR_CONSTRUCTED)) return true; else return false; } /*********************************************************************** * @brief Determines whether or not an object was battlefield spawned * * @param obj_id object * * @return boolean ***********************************************************************/ boolean isBattlefieldSpawned(obj_id object) { if (object == null || object == obj_id.NULL_ID) return false; if (hasObjVar(object, VAR_SPAWNED_BY)) return true; else return false; } /*********************************************************************** * @brief Determines whether or not two objects are of the same * battlefield faction. * * @param obj_id object1 * @param obj_id object2 * * @return boolean ***********************************************************************/ boolean isSameBattlefieldFaction(obj_id object1, obj_id object2) { if (object1 == null || object1 == obj_id.NULL_ID) return false; if (object2 == null || object2 == obj_id.NULL_ID) return false; region bf = battlefield.getBattlefield(object1); region bf2 = battlefield.getBattlefield(object2); if (bf == null || bf2 == null) return false; if (!bf.getName().equals(bf2.getName())) return false; obj_id master_object = battlefield.getMasterObjectFromRegion(bf); int object1_id = pvpBattlefieldGetFaction(object1, bf); int object2_id = pvpBattlefieldGetFaction(object2, bf); //LOG("LOG_CHANNEL", "obj1 ->" + object1_id + " obj2 ->" + object2_id); if (object1_id == object2_id) return true; else return false; } /*********************************************************************** * @brief Determines whether or not the player may join a battlefield game * * @param obj_id master_object * @param obj_id player * @param boolean verbose * * @return boolean ***********************************************************************/ boolean canJoinBattlefield(obj_id master_object, obj_id player, boolean verbose) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (!isBattlefieldActive(master_object)) return true; if (pvpHasAnyTempEnemyFlags(player)) { if (verbose) { LOG("LOG_CHANNEL", player + " ->You cannot enter the battlefield as long as you have temporary enemies."); sendSystemMessageTestingOnly(player, "You cannot enter the battlefield as long as you have temporary enemies."); } return false; } if (hasObjVar(player, VAR_BATTLEFIELD_ENTERED)) { if (master_object == getObjIdObjVar(player, VAR_BATTLEFIELD_ENTERED)) { if (verbose) { LOG("LOG_CHANNEL", player + " ->You must wait for the current battle to end before reentering."); sendSystemMessageTestingOnly(player, "You must wait for the current battle to end before reentering."); } return false; } else return true; } else return true; } /*********************************************************************** * @brief canJoinBattlefield overload * * @param obj_id master_object * @param obj_id player * * @return boolean ***********************************************************************/ boolean canJoinBattlefield(obj_id master_object, obj_id player) { return canJoinBattlefield(master_object, player, false); } /*********************************************************************** * @brief canJoinBattlefield overload * * @param region r battlefield to test * * @return boolean ***********************************************************************/ boolean canJoinBattlefield(region r, obj_id player) { if (r == null) return false; obj_id master_object = getMasterObjectFromRegion(r); return canJoinBattlefield(master_object, player); } /*********************************************************************** * @brief Determines whether or not the player can build a structure. * * @param obj_id master_object * @param obj_id player * * @return boolean ***********************************************************************/ boolean canBuildBattlefieldStructure(obj_id master_object, obj_id player) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (player == null || player == obj_id.NULL_ID) return false; location loc = getLocation(player); region bf = getRegionFromMasterObject(master_object); int faction_id = pvpBattlefieldGetFaction(player, bf); string faction = factions.getFactionNameByHashCode(faction_id); // Check to see if the player has the appropriate skill. if (!utils.isProfession(player, utils.TRADER)) { LOG("LOG_CHANNEL", player + " ->You must have skill as an artisan in order to use the battlefield constructor."); sendSystemMessageTestingOnly(player, "You must have skill as an artisan in order to use the battlefield constructor."); return false; } if (!isNearBattlefieldConstructor(master_object, loc, faction)) { LOG("LOG_CHANNEL", player + " ->You must be near a battlefield constructor owned by your faction."); sendSystemMessageTestingOnly(player, "You must be near a battlefield constructor owned by your faction."); return false; } if (!isBattlefieldActive(master_object)) { LOG("LOG_CHANNEL", player + " ->You can only build in an active battlefield."); sendSystemMessageTestingOnly(player, "You can only build in an active battlefield."); return false; } return true; } /*********************************************************************** * @brief Determines whether or not a barracks is able to build * reinforcements. * * @param obj_id structure * * @return boolean ***********************************************************************/ boolean canBuildReinforcement(obj_id structure) { if (structure == null || structure == obj_id.NULL_ID) return false; if (!hasScript(structure, SCRIPT_BARRACKS)) return false; else { if (hasObjVar(structure, VAR_LAST_BUILD)) { int time = getGameTime(); int build_rate = getIntObjVar(structure, VAR_BUILD_RATE); if (time - getIntObjVar(structure, VAR_LAST_BUILD) <= build_rate) return false; else return true; } else return true; } } /*********************************************************************** * @brief Determines whether or not the player may enter the battlefield * * @param obj_id master_object * * @return boolean ***********************************************************************/ boolean canEnterBattlefield(obj_id master_object, obj_id player) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (!isBattlefieldActive(master_object)) return true; if (hasObjVar(player, VAR_TEAM_FACTION)) return true; else return false; } /*********************************************************************** * @brief canEnterBattlefield * * @param region r * * @return boolean ***********************************************************************/ boolean canEnterBattlefield(region r, obj_id player) { if (r == null) return false; obj_id master_object = getMasterObjectFromRegion(r); return canEnterBattlefield(master_object, player); } /*********************************************************************** * @brief Determines whether or not the player may leave the battlefield * * @param obj_id master_object * @param obj_id player * @param boolean verbose whether or not to display messaging. * * @return boolean ***********************************************************************/ boolean canExitBattlefield(obj_id master_object, obj_id player, boolean verbose) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (hasObjVar(player, VAR_TIME_ENTERED)) { int time_played = getGameTime() - getIntObjVar(player, VAR_TIME_ENTERED); //LOG("LOG_CHANNEL", "time_played ->" + time_played); if (time_played < CONFINEMENT_TIME) { if (verbose) { int time_left = CONFINEMENT_TIME - time_played; int[] conv_time = player_structure.convertSecondsTime(time_left); string time_str = player_structure.assembleTimeRemaining(conv_time); LOG("LOG_CHANNEL", player + " ->You may not leave the battlefield until you have played for another " + time_str); sendSystemMessageTestingOnly(player, "You may not leave the battlefield until you have played for another " + time_str); } return false; } else return true; } else return true; } /*********************************************************************** * @brief Adds an object to the battlefield * * @param obj_id master_object * @param string template template of object to add * @param location loc location to place the object * @param float yaw yaw of the object * @param string faction faction with which to align the object * * @return obj_id object created. Null on fail. ***********************************************************************/ obj_id addBattlefieldObject(obj_id master_object, string template, location loc, float yaw, string faction) { // Create it. obj_id object = createObject(template, loc); if (object == null) { LOG("LOG_CHANNEL", "battlefield::addBattlefieldObject -- unable to create " + template + " in " + master_object); return null; } // Rotate it. setYaw(object, yaw); // Attach battlefield object script attachScript(object, SCRIPT_BATTLEFIELD_OBJECT); // Add it to the base object list. //resizeable obj_id[] base_objects = new obj_id[0]; //if (hasObjVar(master_object, VAR_BASE_OBJECTS)) // base_objects = getResizeableObjIdArrayObjVar(master_object, VAR_BASE_OBJECTS); //base_objects = utils.addElement(base_objects, object); //setObjVar(master_object, VAR_BASE_OBJECTS, base_objects); // Set its faction. int faction_id = getFactionId(faction); region bf = getRegionFromMasterObject(master_object); pvpBattlefieldSetParticipant(object, bf, faction_id); //persistObject(object); return object; } /*********************************************************************** * @brief Removes an object from the battlefield * * @param obj_id object object to remove * * @return boolean ***********************************************************************/ boolean removeBattlefieldObject(obj_id master_object, obj_id object) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (object == null || object == obj_id.NULL_ID) return false; region bf = getRegionFromMasterObject(master_object); pvpBattlefieldSetParticipant(object, bf, 0); messageTo(object, "msgDestroyBattlefieldObject", null, 0.0f, true); return true; } /*********************************************************************** * @brief Overload for removeBattlefieldObject * * @param obj_id object object to remove * * @return boolean ***********************************************************************/ boolean removeBattlefieldObject(obj_id object) { if (object == null || object == obj_id.NULL_ID) return false; region bf = getBattlefield(object); obj_id master_object = getMasterObjectFromRegion(bf); if (master_object == null) return false; return removeBattlefieldObject(master_object, object); } /*********************************************************************** * @brief removes the object from the battlefield object list * without deleting it. This should only be used if it can * be assured that the object will be deleted. * * @param obj_id object object to remove * * @return boolean ***********************************************************************/ boolean removeFromBattlefieldObjectList(obj_id master_object, obj_id object) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (object == null || object == obj_id.NULL_ID) return false; region bf = getRegionFromMasterObject(master_object); pvpBattlefieldSetParticipant(object, bf, 0); return true; } /*********************************************************************** * @brief Adds a mob to the battlefield * * @param obj_id master_object * @param string mob mob name to add (from creature datatable) * @param location loc location to place the mob * @param string faction faction with which to align the mob * * @return obj_id mob created. Null on fail. ***********************************************************************/ obj_id addBattlefieldMob(obj_id master_object, string name, location loc, string faction) { // Create it. obj_id mob = create.createCreature(name, loc, true); if (mob == null) { LOG("LOG_CHANNEL", "battlefield::addBattlefieldMob -- unable to create " + name + " in " + master_object); return null; } // Attach battlefield object script attachScript(mob, SCRIPT_BATTLEFIELD_OBJECT); // Set its faction. int faction_id = getFactionId(faction); region bf = getRegionFromMasterObject(master_object); pvpBattlefieldSetParticipant(mob, bf, faction_id); return mob; } /*********************************************************************** * @brief Adds a battlefield waypoint to the player for a given structure * * @param obj_id master_object * @param obj_id structure * * @return boolean ***********************************************************************/ obj_id addBattlefieldWaypoint(obj_id player, obj_id structure) { if (player == null || player == obj_id.NULL_ID) return null; if (structure == null || structure == obj_id.NULL_ID) return null; obj_id waypoint = createWaypointInDatapad(player, structure); if (!isIdValid(waypoint)) return null; setWaypointVisible(waypoint, true); setWaypointActive(waypoint, true); setWaypointName(waypoint, getName(structure)); // Record the waypoint in the player's waypoint list. resizeable obj_id[] waypoint_list = new obj_id[0]; if (hasObjVar(player, VAR_WAYPOINTS)) waypoint_list = getResizeableObjIdArrayObjVar(player, VAR_WAYPOINTS); waypoint_list = utils.addElement(waypoint_list, waypoint); if(waypoint_list.length > 0) { // Zero length array check setObjVar(player, VAR_WAYPOINTS, waypoint_list); } LOG("LOG_CHANNEL", "battlefield::AddBattlefieldWaypoint -- adding waypoint(" + waypoint + ") to player " + player + " for " + structure); return waypoint; } /*********************************************************************** * @brief Removes a battlefield waypoint from a player. * * @param obj_id player * @param obj_id waypoint * * @return boolean ***********************************************************************/ boolean removeBattlefieldWaypoint(obj_id player, obj_id waypoint) { if (player == null || player == obj_id.NULL_ID) return false; if (waypoint == null || waypoint == obj_id.NULL_ID) return false; if (hasObjVar(player, VAR_WAYPOINTS)) { resizeable obj_id[] waypoint_list = getResizeableObjIdArrayObjVar(player, VAR_WAYPOINTS); int idx = utils.getElementPositionInArray(waypoint_list, waypoint); if (idx != -1) { waypoint_list = utils.removeElementAt(waypoint_list, idx); if (waypoint_list.length < 1) removeObjVar(player, VAR_WAYPOINTS); else setObjVar(player, VAR_WAYPOINTS, waypoint_list); } } destroyObject(waypoint); return true; } /*********************************************************************** * @brief Destroys the battlefield and everything within it. * * @param obj_id master_object master battlefield object * * @return boolean ***********************************************************************/ boolean destroyBattlefield(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return false; LOG("LOG_CHANNEL", "destroying " + master_object); // destroy the region region r = getRegionFromMasterObject(master_object); deleteRegion(r); // destroy the region markers if (hasObjVar(master_object, VAR_MARKERS)) { obj_id[] markers = getObjIdArrayObjVar(master_object, VAR_MARKERS); for (int i = 0; i < markers.length; i++) destroyObject(markers[i]); } // destroy the items within the battlefield destroyBaseObjects(master_object); // destroy the master object destroyObject(master_object); return true; } /*********************************************************************** * @brief Overload for destroyBattlefield * * @param region battlefield to destroy * * @return boolean ***********************************************************************/ boolean destroyBattlefield(region r) { if (r == null) return false; obj_id master_object = getMasterObjectFromRegion(r); return destroyBattlefield(master_object); } /*********************************************************************** * @brief Destroys a battlefield's base objects * * @param obj_id master_object * * @return boolean ***********************************************************************/ boolean destroyBaseObjects(obj_id master_object) { //LOG("LOG_CHANNEL", "destroyBaseObjects -- " + master_object); if (master_object == null || master_object == obj_id.NULL_ID) return false; region reg = getRegionFromMasterObject(master_object); obj_id[] base_objects = pvpBattlefieldGetParticipantsForFaction(reg, 0); if (base_objects != null) { //LOG("LOG_CHANNEL", "destroyBaseObjects -- " + master_object); for (int i = 0; i < base_objects.length; i++) { if (hasScript(base_objects[i], SCRIPT_BATTLEFIELD_OBJECT)) messageTo(base_objects[i], "msgDestroyBattlefieldObject", null, 30.0f, false); } return true; } else return false; } /*********************************************************************** * @brief Returns the region of the specified master object * * @param obj_id master battlefield object * * @return region of battlefield null on failure ***********************************************************************/ region getRegionFromMasterObject(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; string regionPlanet = getStringObjVar(master_object, VAR_PLANET); string regionName = getStringObjVar(master_object, VAR_NAME); return getRegion(regionPlanet, regionName); } /*********************************************************************** * @brief Returns the master object of the specified region * * @param region battlefield battlefield object * * @return obj_id of master object null on failure ***********************************************************************/ obj_id getMasterObjectFromRegion(region battlefield) { if (battlefield == null) return null; return getBattlefieldRegionMasterObject(battlefield); } /*********************************************************************** * @brief Returns the battlefield's name * * @param obj_id master battlefield object * * @return string null on failure ***********************************************************************/ string getBattlefieldName(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; string name = getStringObjVar(master_object, VAR_NAME); if ( name.startsWith("@") ) { // strip the string id table from the name name = name.substring(name.indexOf(":") + 1); } return name; } /*********************************************************************** * @brief Overload for getBattlefieldName * * @param region r battlefield region * * @return string null on failure ***********************************************************************/ string getBattlefieldName(region r) { if (r == null) return null; string name = r.getName(); if ( name.startsWith("@") ) { // strip the string id table from the name name = name.substring(name.indexOf(":") + 1); } return name; } /*********************************************************************** * @brief Returns the battlefield's localized name * * @param obj_id master battlefield object * * @return string null on failure ***********************************************************************/ string getBattlefieldLocalizedName(obj_id master_object) { if (!isIdValid(master_object)) return null; string name = getBattlefieldName(master_object).toLowerCase(); string_id name_id = utils.unpackString("@battlefield:" + name); return localize(name_id); } /*********************************************************************** * @brief Returns the radius of the battlefield * * @param region r * * @return float -1.0f on fail ***********************************************************************/ float getBattlefieldExtent(region r) { if (r == null) return -1.0f; obj_id master_object = getMasterObjectFromRegion(r); return getFloatObjVar(master_object, VAR_EXTENT); } /*********************************************************************** * @brief Overload of BattlefieldExtent * * @param obj_id master_object * * @return float -1.0f on fail ***********************************************************************/ float getBattlefieldExtent(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return -1.0f; return getFloatObjVar(master_object, VAR_EXTENT); } /*********************************************************************** * @brief Returns the location of the battlefield * * @param obj_id master_object * * @return location null on fail *********************************************************************/ location getBattlefieldLocation(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; return getLocation(master_object); } /*********************************************************************** * @brief Returns the location of the battlefield * * @param region r * * @return location null on fail *********************************************************************/ location getBattlefieldLocation(region r) { if (r == null) return null; obj_id master_object = getMasterObjectFromRegion(r); return getBattlefieldLocation(master_object); } /*********************************************************************** * @brief Returns the version of the battlefield * * @param obj_id master_object * * @return int *********************************************************************/ int getBattlefieldVersion(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; if (hasObjVar(master_object, VAR_VERSION)) return getIntObjVar(master_object, VAR_VERSION); else return -1; } /*********************************************************************** * @brief Returns the time remaining in a battlefield * * @param obj_id master_object * * @return int -1 on fail *********************************************************************/ int getGameTimeRemaining(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; if (hasObjVar(master_object, VAR_TIME_REMAINING)) return getIntObjVar(master_object, VAR_TIME_REMAINING); else return -1; } /*********************************************************************** * @brief Overload for getGameTimeRemaining * * @param region r * * @return int -1 on fail *********************************************************************/ int getGameTimeRemaining(region r) { if (r == null) return -1; obj_id master_object = getMasterObjectFromRegion(r); return getGameTimeRemaining(master_object); } /*********************************************************************** * @brief returns the battlefield's game type * * @param obj_id master_object * * @return string null on fail *********************************************************************/ string getBattlefieldGameType(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; return getStringObjVar(master_object, VAR_GAME_TYPE); } /*********************************************************************** * @brief Overload for getBattlefieldGameType * * @param region r * * @return string null on fail *********************************************************************/ string getBattlefieldGameType(region r) { if (r == null) return null; obj_id master_object = getMasterObjectFromRegion(r); return getBattlefieldGameType(master_object); } /*********************************************************************** * @brief returns the battlefield's next game time stamp * * @param obj_id master_object * * @return int -1 on fail *********************************************************************/ int getNextGameTime(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; if (hasObjVar(master_object, VAR_NEXT_GAME)) { return getIntObjVar(master_object, VAR_NEXT_GAME); } else return -1; } /*********************************************************************** * @brief Overload for getNextGameTime * * @param region r * * @return int -1 on fail *********************************************************************/ int getNextGameTime(region r) { if (r == null) return -1; obj_id master_object = getMasterObjectFromRegion(r); return getNextGameTime(master_object); } /*********************************************************************** * @brief returns the battlefield's game duration * * @param obj_id master_object * * @return int -1 on fail *********************************************************************/ int getGameDuration(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; return getIntObjVar(master_object, VAR_GAME_DURATION); } /*********************************************************************** * @brief Overload for getBattlefieldRestartTime * * @param region r * * @return int -1 on fail *********************************************************************/ int getGameDuration(region r) { if (r == null) return -1; obj_id master_object = getMasterObjectFromRegion(r); return getGameDuration(master_object); } /*********************************************************************** * @brief returns the amount of time a player has spent in the * battlefield * * @param obj_id player * * @return int -1 on fail or the player is not in the battlefield *********************************************************************/ int getTimeSpentInBattlefield(obj_id player) { if (player == null || player == obj_id.NULL_ID) return -1; region bf = getBattlefield(player); if (bf == null) return -1; int time_entered = getIntObjVar(player, VAR_TIME_ENTERED); int time_exited = getGameTime(); if (hasObjVar(player, VAR_TIME_EXITED)) time_exited = getIntObjVar(player, VAR_TIME_EXITED); return time_exited - time_entered; } /*********************************************************************** * @brief returns a list of the names of structures that may be built * on the battlefield. * * @param obj_id master_object * @param string faction the faction for which to find buildable * structures * * @return string[] null on fail or if there are none *********************************************************************/ string[] getBuildableStructures(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return null; int idx = getBattlefieldIndex(master_object, BUILDABLE_STRUCTURE_DATATABLE); if (idx == -1) return null; resizeable string[] buildable_objects = new string[0]; int num_items = dataTableGetNumRows(BUILDABLE_STRUCTURE_DATATABLE); if (num_items > idx + 1) { for (int i = idx + 1; i < num_items; i++) { dictionary row = dataTableGetRow(BUILDABLE_STRUCTURE_DATATABLE, i); string bf_name = row.getString(DATATABLE_COL_NAME); string structure_faction = row.getString(DATATABLE_COL_FACTION); if (bf_name.length() > 0) return buildable_objects; //LOG("LOG_CHANNEL", "structure_faction ->" + structure_faction); if (structure_faction.equals(faction) || structure_faction.equals("ALL") || faction.equals("ANY")) { string structure_name = row.getString(DATATABLE_COL_BUILDING_NAME); buildable_objects = utils.addElement(buildable_objects, structure_name); } } } if (buildable_objects.length > 0) return buildable_objects; else return null; } /*********************************************************************** * @brief returns a dictionary of the buildable structure's * construction stats. * * @param obj_id master_object * @param int index Index of 0 refers to the first * structure after the battlefield name. * * @return dictionary keys: template, name, cost, construction_time, * faction *********************************************************************/ dictionary getBuildableStructureStats(obj_id master_object, int index) { if (master_object == null || master_object == obj_id.NULL_ID) return null; // Find the position of the object in the datatable. int bf_idx = getBattlefieldIndex(master_object, BUILDABLE_STRUCTURE_DATATABLE); if (bf_idx == -1) return null; // Check to make sure the index does not go into the next battlefield's entries string[] buildable_structures = getBuildableStructures(master_object, "ANY"); if (index > buildable_structures.length) return null; int structure_idx = bf_idx + index + 1; //LOG("LOG_CHANNEL", "struct_idx ->" + structure_idx); int num_items = dataTableGetNumRows(BUILDABLE_STRUCTURE_DATATABLE); if (num_items > structure_idx) return dataTableGetRow(BUILDABLE_STRUCTURE_DATATABLE, structure_idx); else return null; } /*********************************************************************** * @brief Overload for getBuildableStructureStats. Uses template * or name instead of index. * * @param obj_id master_object * @param string template template or name of buildable structure * * @return dictionary keys: template, name, cost, construction_time, * faction *********************************************************************/ dictionary getBuildableStructureStats(obj_id master_object, string template) { if (master_object == null || master_object == obj_id.NULL_ID) return null; // Find the position of the object in the datatable. int bf_idx = getBattlefieldIndex(master_object, BUILDABLE_STRUCTURE_DATATABLE); if (bf_idx == -1) return null; string[] structures = getBuildableStructures(master_object, "ANY"); if (structures == null) return null; for (int i = 0; i < structures.length; i++) { dictionary stats = dataTableGetRow(BUILDABLE_STRUCTURE_DATATABLE, i + 1 + bf_idx); if (stats.getString("template").equals(template)) return stats; else if (stats.getString("name").equals(template)) return stats; } return null; } /*********************************************************************** * @brief Attachs the battlefield's game script to the master object * * @param obj_id master_object * * @return string null on fail *********************************************************************/ boolean attachGameScript(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return false; string script = GAME_SCRIPT_PATH + getBattlefieldGameType(master_object).toLowerCase(); LOG("LOG_CHANNEL", "battlefield::attachGameScript -- attaching " + script + " to " + master_object); if (!hasScript(master_object, script)) { attachScript(master_object, script); return true; } else return false; } /*********************************************************************** * @brief Removes the battlefield's game script to the master object * * @param obj_id master_object * * @return string null on fail *********************************************************************/ boolean detachGameScript(obj_id master_object) { if (!isIdValid(master_object)) { LOG("LOG_CHANNEL", "battlefield::detachGameScript -- master_object is null"); return false; } string script; string game_type = getBattlefieldGameType(master_object); if (game_type != null) script = GAME_SCRIPT_PATH + game_type.toLowerCase(); else { LOG("LOG_CHANNEL", "battlefield::detachGameScript -- game_type is null for " + master_object); return false; } LOG("LOG_CHANNEL", "battlefield::detachGameScript -- detaching " + script + " to " + master_object); if (hasScript(master_object, script)) { detachScript(master_object, script); return true; } else return false; } /*********************************************************************** * @brief returns the battlefield's chatroom root name * * @param obj_id master_object * * @return string null on fail *********************************************************************/ string getChatRoomName(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; string bf_name = getBattlefieldName(master_object); string chat_name = "SWG." + getGalaxyName() + "." + getCurrentSceneName() + ".battlefield." + bf_name; return chat_name; } /*********************************************************************** * @brief returns the battlefield's all faction chatroom root name * * @param obj_id master_object * * @return string null on fail *********************************************************************/ string getChatRoomNameAllFactions(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; return getChatRoomName(master_object) + ".allFactions"; } /*********************************************************************** * @brief returns a faction's battlefield chatroom root name * * @param obj_id master_object * * @return string null on fail *********************************************************************/ string getChatRoomNameFaction(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return null; return getChatRoomName(master_object) + "." + faction; } /*********************************************************************** * @brief returns the number of registered kills for a given faction * * @param obj_id master_object * @param string faction * * @return int -1 on fail *********************************************************************/ int getFactionKills(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; string objVar_team_kills = VAR_KILLS + faction; if (hasObjVar(master_object, objVar_team_kills)) return getIntObjVar(master_object, objVar_team_kills); else return 0; } /*********************************************************************** * @brief returns the number of deaths for a given faction * * @param obj_id master_object * @param string faction * * @return int -1 on fail *********************************************************************/ int getFactionDeaths(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; string objVar_team_deaths = VAR_DEATHS + faction; if (hasObjVar(master_object, objVar_team_deaths)) return getIntObjVar(master_object, objVar_team_deaths); else return 0; } /*********************************************************************** * @brief returns the participants in the battlefield game * * @param obj_id master_object * * @return obj_id[] null on error or no game in progress *********************************************************************/ obj_id[] getParticipantsOnBattlefield(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; if (hasObjVar(master_object, VAR_PARTICIPANTS)) return utils.getObjIdBatchObjVar(master_object, VAR_PARTICIPANTS); else return null; } /*********************************************************************** * @brief Overload for getParticipantsOnBattlefield * * @param region r * * @return obj_id[] null on error or no game in progress *********************************************************************/ obj_id[] getParticipantsOnBattlefield(region r) { if (r == null) return null; obj_id master_object = getMasterObjectFromRegion(r); return getParticipantsOnBattlefield(master_object); } /*********************************************************************** * @brief returns the specified faction's team in the battlefield game * * @param obj_id master_object * * @return obj_id[] null on fail *********************************************************************/ obj_id[] getFactionTeam(obj_id master_object, string faction) { LOG("LOG_CHANNEL", "battlefield.getFactionTeam"); if (master_object == null || master_object == obj_id.NULL_ID) return null; obj_id[] players = getPlayersOnBattlefield(master_object); resizeable obj_id[] faction_team = new obj_id[0]; if (players != null) { for (int i = 0; i < players.length; i++) { string player_faction = getPlayerTeamFaction(players[i]); if (player_faction != null) { if (player_faction.equals(faction)) faction_team = utils.addElement(faction_team, players[i]); } } } else return null; return faction_team; } /*********************************************************************** * @brief Overload for getFactionTeam * * @param region r * * @return obj_id[] null on error or no game in progress *********************************************************************/ obj_id[] getFactionTeam(region r, string faction) { if (r == null) return null; obj_id master_object = getMasterObjectFromRegion(r); return getFactionTeam(master_object, faction); } /*********************************************************************** * @brief returns the battlefield's player allowed factions * * @param obj_id master_object * * @return string[] null on fail *********************************************************************/ string[] getFactionsAllowed(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; return getStringArrayObjVar(master_object, VAR_FACTIONS_ALLOWED); } /*********************************************************************** * @brief Overload for getFactionsAllowed * * @param region r * * @return string[] null on fail *********************************************************************/ string[] getFactionsAllowed(region r) { if (r == null) return null; obj_id master_object = getMasterObjectFromRegion(r); return getFactionsAllowed(master_object); } /*********************************************************************** * @brief returns the player factions remaining in a game * * @param obj_id master_object * * @return string[] null on fail *********************************************************************/ string[] getFactionsRemaining(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; if (hasObjVar(master_object, VAR_FACTIONS_REMAINING)) { return getStringArrayObjVar(master_object, VAR_FACTIONS_REMAINING); } else return null; } /*********************************************************************** * @brief returns the ai factions allowed in a game * * @param obj_id master_object * * @return string[] null on fail *********************************************************************/ string[] getAIFactionsAllowed(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; if (hasObjVar(master_object, VAR_FACTIONS_AI_ALLOWED)) { return getStringArrayObjVar(master_object, VAR_FACTIONS_AI_ALLOWED); } else return null; } /*********************************************************************** * @brief returns the ai factions remaining in a game * * @param obj_id master_object * * @return string[] null on fail *********************************************************************/ string[] getAIFactionsRemaining(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; if (hasObjVar(master_object, VAR_FACTIONS_AI_REMAINING)) { return getStringArrayObjVar(master_object, VAR_FACTIONS_AI_REMAINING); } else return null; } /*********************************************************************** * @brief returns a list of both ai and player factions remaining * * @param obj_id master_object * * @return string[] null on fail *********************************************************************/ string[] getAllFactionsRemaining(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; string[] factions_remaining_array = getFactionsRemaining(master_object); resizeable string[] factions_remaining = factions_remaining_array; string[] ai_factions = getAIFactionsRemaining(master_object); if (factions_remaining != null && ai_factions != null) { factions_remaining = utils.concatArrays(factions_remaining, ai_factions); return factions_remaining; } else if (ai_factions == null) return factions_remaining; else if (factions_remaining == null) return ai_factions; else { LOG("LOG_CHANNEL", "battlefield::getAllFactionsRemaining -- there are no factions remaining for " + master_object); return null; } } /*********************************************************************** * @brief returns a list of both ai and player factions allowed * * @param obj_id master_object * * @return string[] null on fail *********************************************************************/ string[] getAllFactionsAllowed(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; string[] factions_allowed_array = getFactionsAllowed(master_object); resizeable string[] factions_allowed = factions_allowed_array; string[] ai_factions = getAIFactionsAllowed(master_object); if (factions_allowed != null && ai_factions != null) { factions_allowed = utils.concatArrays(factions_allowed, ai_factions); return factions_allowed; } else if (ai_factions == null) return factions_allowed; else if (factions_allowed == null) return ai_factions; else { LOG("LOG_CHANNEL", "battlefield::getAllFactionsRemaining -- there are no factions remaining for " + master_object); return null; } } /*********************************************************************** * @brief returns a faction id from the string * * @param string faction * * @return return int *********************************************************************/ int getFactionId(string faction) { int faction_num = factions.getFactionNumber(faction); if (faction_num == -1) return 0; int faction_id = dataTableGetInt("datatables/faction/faction.iff", faction_num, "pvpFaction"); return faction_id; } /*********************************************************************** * @brief returns the battlefield's minimum game restart time * * @param obj_id master_object * * @return int -1 on fail *********************************************************************/ int getGameRestartMinimum(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; return getIntObjVar(master_object, VAR_RESTART_TIME_MIN); } /*********************************************************************** * @brief returns the battlefield's maximum game restart time * * @param obj_id master_object * * @return int -1 on fail *********************************************************************/ int getGameRestartMaximum(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; return getIntObjVar(master_object, VAR_RESTART_TIME_MAX); } /*********************************************************************** * @brief returns a faction's build point total * * @param obj_id master_object * @params string faction * * @return int -1 on fail *********************************************************************/ int getFactionBuildPoints(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; string objVar_name = VAR_BUILD_POINTS + faction; if (hasObjVar(master_object, objVar_name)) return getIntObjVar(master_object, objVar_name); else return -1; } /*********************************************************************** * @brief returns all of the objects in the battlefield marked * as game critical. * * @param obj_id master_object * * @return obj_id[] null on fail *********************************************************************/ obj_id[] getGameCriticalObjects(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; resizeable obj_id[] critical_items = new obj_id[0]; region bf = getRegionFromMasterObject(master_object); obj_id[] items = pvpBattlefieldGetParticipantsForFaction(bf, 0); if (items != null) { for (int i = 0; i < items.length; i++) { // only critical items have the game critical objvar if (hasObjVar(items[i], VAR_GAME_CRITICAL)) critical_items = utils.addElement(critical_items, items[i]); } } if (critical_items.length > 0) return critical_items; else return null; } /*********************************************************************** * @brief gets all players within the battlefield. Performs an * extensive search of the entire battlefield. * * @param obj_id master_object * * @return obj_id[] null on fail *********************************************************************/ obj_id[] getPlayersOnBattlefieldComplete(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; float radius = getBattlefieldExtent(master_object); // The master object is always at the center of the battlefield location loc = getLocation(master_object); resizeable obj_id[] players = new obj_id[0]; obj_id[] items = getObjectsInRange(loc, radius); if (items != null) { for (int i = 0; i < items.length; i++) { if (isPlayer(items[i])) players = utils.addElement(players, items[i]); else if (player_structure.isBuilding(items[i])) { // Look for players inside each building. obj_id[] player_building = player_structure.getPlayersInBuilding(items[i]); if (player_building != null) players = utils.concatArrays(players, player_building); } } } return players; } /*********************************************************************** * @brief gets all players within the battlefield. Using the prebuilt * list. Does not search through everything in the battlefield. * * @param obj_id master_object * * @return obj_id[] null on fail *********************************************************************/ obj_id[] getPlayersOnBattlefield(obj_id master_object) { if (master_object == null || master_object == obj_id.NULL_ID) return null; if (hasObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD)) { obj_id[] players = utils.getObjIdBatchObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD); if (players == null || players.length < 1) { LOG("LOG_CHANNEL", "battlefield.getPlayersOnBattlefield -- players is null."); return null; } resizeable obj_id[] loaded_players = new obj_id[0]; // Only return the players that are loaded. Disconnected players don't trigger for (int i = 0; i < players.length; i++) { LOG("LOG_CHANNEL", "battlefield::getPlayersOnBattlefield -- players[" + i + "] ->" + players[i]); if (players[i].isLoaded()) loaded_players = utils.addElement(loaded_players, players[i]); } if (loaded_players.length < 0) return null; else return loaded_players; } else return null; } /*********************************************************************** * @brief Overload for getPlayersOnBattlefield * * @param region r battlefield * * @return boolean ***********************************************************************/ obj_id[] getPlayersOnBattlefield(region r) { if (r == null) return null; obj_id master_object = getMasterObjectFromRegion(r); return getPlayersOnBattlefield(master_object); } /*********************************************************************** * @brief Returns the player's declared battlefield faction * * @param obj_id player * * @return string null on fail *********************************************************************/ string getPlayerTeamFaction(obj_id player) { if (player == null || player == obj_id.NULL_ID) return null; if (hasObjVar(player, VAR_TEAM_FACTION)) return getStringObjVar(player, VAR_TEAM_FACTION); else return null; } /*********************************************************************** * @brief Returns the master object of the battlefield a player entered * * @param obj_id player * * @return obj_id null on fail *********************************************************************/ obj_id getBattlefieldEntered(obj_id player) { if (player == null || player == obj_id.NULL_ID) return null; if (hasObjVar(player, VAR_BATTLEFIELD_ENTERED)) return getObjIdObjVar(player, VAR_BATTLEFIELD_ENTERED); else return null; } /*********************************************************************** * @brief Returns the battlefield's location in the datatable * * @param obj_id master_object * * @return int -1 on fail or no match *********************************************************************/ int getBattlefieldIndex(obj_id master_object, string datatable) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; int numItems = dataTableGetNumRows(datatable); string bf_name = getBattlefieldName(master_object); string bf_area = getCurrentSceneName(); for (int i = 0; i < numItems; i++) { string name = dataTableGetString(datatable, i, DATATABLE_COL_NAME); if (datatable == BATTLEFIELD_DATATABLE) { // Check for area and name for the battlefield table. string area = dataTableGetString(datatable, i, DATATABLE_COL_AREA); if (area.equals(bf_area)) { if (name.equals(bf_name)) return i; } } else { // Otherwise, just check for the name. if (name.equals(bf_name)) return i; } } return -1; } /*********************************************************************** * @brief Gets a faction's starting location * * @param obj_id master_object * @param string faction * * @return location null on fail or if there is no starting location *********************************************************************/ location getFactionStartLocation(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return null; string[] factions_allowed = getFactionsAllowed(master_object); if (faction == null) return null; int idx = utils.getElementPositionInArray(factions_allowed, faction); if (idx == -1) return null; location[] start_locations = getLocationArrayObjVar(master_object, VAR_START_LOCATIONS); location loc = start_locations[idx]; // If all three coordinates are 0, then the starting location was not specified. if (loc.x == 0.0f && loc.y == 0.0f && loc.z == 0.0f) return null; else return loc; } /*********************************************************************** * @brief Returns a dictionary of data for a given spawner * * @param string spawner_name reference name used in the battlefield * datatables. * * @return dictionary "spawn_template" - string array of templates to spawn * "min_number" - int array of minimum number to spawn * "max_number" - int array of maximum number to spawn * "weight" - int array of probability weights *********************************************************************/ dictionary getSpawnerData(string spawner_name) { //LOG("LOG_CHANNEL", "spawner_name ->" + spawner_name); if (spawner_name == null) { LOG("LOG_CHANNEL", "battlefield::getSpawnerData -- spawner_name is null"); return null; } int idx = dataTableSearchColumnForString(spawner_name, DATATABLE_COL_SPAWNER_TYPE, SPAWNER_DATATABLE); //LOG("LOG_CHANNEL", "idx ->" + idx); if (idx == -1) { LOG("LOG_CHANNEL", "battlefield::getSpawnerData -- unable to find an entry for " + spawner_name); return null; } int num_items = dataTableGetNumRows(SPAWNER_DATATABLE); resizeable string[] spawn_template = new string[0]; resizeable int[] min_number = new int[0]; resizeable int[] max_number = new int[0]; resizeable int[] weight = new int[0]; for (int i = idx + 1; i < num_items; i++) { //LOG("LOG_CHANNEL", "battlefield::getSpawnerData -- " + i); dictionary row = dataTableGetRow(SPAWNER_DATATABLE, i); // When the next spawner name is reached, we've gotten everything there is to get. if (row.getString(DATATABLE_COL_SPAWNER_TYPE).length() > 0) break; else { spawn_template = utils.addElement(spawn_template, row.getString(DATATABLE_COL_SPAWNER_TEMPLATE)); min_number = utils.addElement(min_number, row.getInt(DATATABLE_COL_SPAWNER_MIN_NUMBER)); max_number = utils.addElement(max_number, row.getInt(DATATABLE_COL_SPAWNER_MAX_NUMBER)); weight = utils.addElement(weight, row.getInt(DATATABLE_COL_SPAWNER_WEIGHT)); } } dictionary spawn_data = new dictionary(); spawn_data.put("spawn_template", spawn_template); spawn_data.put("min_number", min_number); spawn_data.put("max_number", max_number); spawn_data.put("weight", weight); return spawn_data; } /*********************************************************************** * @brief Creates random spawn for the specified spawner * * @param obj_id master_object * @param string spawner_name reference name used in the battlefield * datatables. * * @return obj_id[] returns the creatures spawned. *********************************************************************/ obj_id[] createRandomSpawn(obj_id master_object, obj_id spawner) { //LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- spawner ->" + spawner + " master_object ->" + master_object); if (spawner == null || spawner == obj_id.NULL_ID) { LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- spawner is null."); return null; } int max_population = getIntObjVar(spawner, VAR_SPAWNER_MAX_POPULATION); int max_spawn = getIntObjVar(spawner, VAR_SPAWNER_MAX); int current_population = 0; if (hasObjVar(spawner, VAR_SPAWNER_CURRENT_POPULATION)) current_population = getIntObjVar(spawner, VAR_SPAWNER_CURRENT_POPULATION); int current_spawn = 0; if (hasObjVar(spawner, VAR_SPAWNER_CURRENT)) current_spawn = getIntObjVar(spawner, VAR_SPAWNER_CURRENT); if (current_population >= max_population) { // Population can never exceed the maximum //LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- Max population already reached for " + spawner); return null; } if (current_spawn >= max_spawn) { // Population can never exceed the maximum //LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- Max number of spawns already reached for " + spawner); return null; } string spawner_type = getStringObjVar(spawner, VAR_SPAWNER_TYPE); dictionary spawn_data = getSpawnerData(spawner_type); //LOG("LOG_CHANNEL", "spawn_data ->" + spawn_data); if (spawn_data == null) { LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- spawn_data is null for " + spawner); return null; } string[] spawn_template = spawn_data.getStringArray("spawn_template"); int[] min_number = spawn_data.getIntArray("min_number"); int[] max_number = spawn_data.getIntArray("max_number"); int[] weight = spawn_data.getIntArray("weight"); if (spawn_template == null || min_number == null || max_number == null || weight == null) { LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- spawn data contains a null array."); return null; } // Determine which template to use based on the probability weights int total_weight = 0; for (int i = 0; i < weight.length; i++) { // Find the total of all weight probabilities. total_weight = total_weight + weight[i]; } //LOG("LOG_CHANNEL", "total_weight ->" + total_weight); if (total_weight < 1) { LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- total probility weight is < 1 for " + spawner); return null; } int weight_index = rand(1, total_weight); //LOG("LOG_CHANNEL", "weight_index ->" + weight_index); int array_index = -1; for (int i = 0; i < weight.length; i++) { // Turn the weight_index into an array index. weight_index = weight_index - weight[i]; if (weight_index < 1) { array_index = i; break; } } //LOG("LOG_CHANNEL", "array_index ->" + array_index); if (array_index == -1) { LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- unable to find an array index for " + spawner); return null; } // Now that we've got the index, create the critters. int num_spawn = rand(min_number[array_index], max_number[array_index]); string template = spawn_template[array_index]; location spawner_loc = getLocation(spawner); region bf = getRegionFromMasterObject(master_object); int faction_id = pvpBattlefieldGetFaction(spawner, bf); string faction = factions.getFactionNameByHashCode(faction_id); resizeable obj_id[] spawned_mobs = new obj_id[0]; //LOG("LOG_CHANNEL", "num_spawn ->" + num_spawn + " template ->" + template); while (num_spawn > 0) { if (max_population > current_population) { location spawn_loc = utils.getRandomAwayLocation(spawner_loc, 5.0f, 10.0f); obj_id mob = addBattlefieldMob(master_object, template, spawn_loc, faction); wander(mob); //LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- " + mob + " created."); spawned_mobs = utils.addElement(spawned_mobs, mob); // Mark it as battlefield constructed setObjVar(mob, battlefield.VAR_CONSTRUCTED, 1); // Keep track of the spawner and battlefield where the mob originated. setObjVar(mob, VAR_SPAWNED_BY, spawner); setObjVar(mob, VAR_SPAWNED_BATTLEFIELD, master_object); //LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- mob ->" + mob); current_population++; num_spawn--; } else break; } if (spawned_mobs.length < 1) { LOG("LOG_CHANNEL", "battlefield::createRandomSpawn -- unable to create spawn for " + spawner); return null; } else { setObjVar(spawner, VAR_SPAWNER_CURRENT_POPULATION, current_population); setObjVar(spawner, VAR_SPAWNER_CURRENT, current_spawn + 1); return spawned_mobs; } } /*********************************************************************** * @brief Sends a chat message to the battlefield players. * * @param obj_id master_object * * @return boolean false on fail *********************************************************************/ boolean sendBattlefieldMessage(obj_id master_object, string text) { if (master_object == null || master_object == obj_id.NULL_ID) return false; string chatroom = getChatRoomNameAllFactions(master_object); LOG("LOG_CHANNEL", "chatroom ->" + chatroom); chatSendToRoom(chatroom, text, ""); LOG("LOG_CHANNEL", master_object + " (Battlefield Message) ->" + text); return true; } /*********************************************************************** * @brief Overload for sendBattlefieldMessage * * @param region r battlefield * * @return boolean ***********************************************************************/ boolean sendBattlefieldMessage(region r, string text) { if (r == null) return false; obj_id master_object = getMasterObjectFromRegion(r); return sendBattlefieldMessage(master_object, text); } /*********************************************************************** * @brief Sends a chat message to a specified faction * * @param obj_id master_object * * @return boolean false on fail *********************************************************************/ boolean sendFactionMessage(obj_id master_object, string faction, string text) { if (master_object == null || master_object == obj_id.NULL_ID) return false; string[] factions_allowed = getFactionsAllowed(master_object); int idx = utils.getElementPositionInArray(factions_allowed, faction); if (idx != -1) { string chatroom = getChatRoomNameFaction(master_object, faction); chatSendToRoom(chatroom, text, ""); LOG("LOG_CHANNEL", master_object + " (Battlefield " + faction + " Message) ->" + text); return true; } else return false; } /*********************************************************************** * @brief Overload for sendFactionMessage * * @param region r battlefield * * @return boolean ***********************************************************************/ boolean sendFactionMessage(region r, string faction, string text) { if (r == null) return false; obj_id master_object = getMasterObjectFromRegion(r); return sendFactionMessage(master_object, faction, text); } /*********************************************************************** * @brief records a kill during a battlefield game. * * @param obj_id killer player who scored the kill. * @param obj_id victim player who was killed. * @param obj_id master_object * * @return boolean false on fail *********************************************************************/ boolean registerBattlefieldKill(obj_id killer, obj_id victim, obj_id master_object) { if (killer == null || killer == obj_id.NULL_ID) return false; if (master_object == null || master_object == obj_id.NULL_ID) return false; if (victim == null || victim == obj_id.NULL_ID) return false; if (!isBattlefieldActive(master_object)) return false; // Give credit for the kill region bf = getRegionFromMasterObject(master_object); if (isMob(killer) && isMob(victim)) { if (killer != victim) { int faction_id = pvpBattlefieldGetFaction(killer, bf); string faction = factions.getFactionNameByHashCode(faction_id); if (faction == null) return false; int faction_kills = 0; string objVar_team_kills = VAR_KILLS + faction; if (hasObjVar(master_object, objVar_team_kills)) faction_kills = getIntObjVar(master_object, objVar_team_kills); faction_kills++; setObjVar(master_object, objVar_team_kills, faction_kills); } } // Put a death on the faction of the victim if (isMob(victim)) { int faction_id = pvpBattlefieldGetFaction(victim, bf); string faction = factions.getFactionNameByHashCode(faction_id); if (faction == null) return false; int faction_deaths = 0; string objVar_team_deaths = VAR_DEATHS + faction; if (hasObjVar(master_object, objVar_team_deaths)) faction_deaths = getIntObjVar(master_object, objVar_team_deaths); faction_deaths++; setObjVar(master_object, objVar_team_deaths, faction_deaths); } // Send a message enabling the specific game script to do its thing with the kill. dictionary params = new dictionary(); params.put("killer", killer); params.put("victim", victim); messageTo(master_object, "msgBattlefieldKill", params, 0.0f, true); return true; } /*********************************************************************** * @brief Adds a player to the player list. * * @param obj_id player * @param obj_id master_object * * @return bolean *********************************************************************/ boolean addPlayerToPlayerList(obj_id player, obj_id master_object) { if (player == null || player == obj_id.NULL_ID) return false; if (master_object == null || master_object == obj_id.NULL_ID) return false; resizeable obj_id[] players = new obj_id[0]; if (hasObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD)) //players = getResizeableObjIdArrayObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD); players = utils.getResizeableObjIdBatchObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD); int idx = utils.getElementPositionInArray(players, player); if (idx != -1) return false; else { players = utils.addElement(players, player); //setObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD, players); removeObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD); utils.setResizeableBatchObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD, players); } return true; } /*********************************************************************** * @brief Removes a player to the player list. * * @param obj_id player * @param obj_id master_object * * @return bolean *********************************************************************/ boolean removePlayerFromPlayerList(obj_id player, obj_id master_object) { if (player == null || player == obj_id.NULL_ID) return false; if (master_object == null || master_object == obj_id.NULL_ID) return false; if (!hasObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD)) return false; resizeable obj_id[] players = utils.getResizeableObjIdBatchObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD); //resizeable obj_id[] players = utils.getResizeableObjIdBatchObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD); int idx = utils.getElementPositionInArray(players, player); if (idx == -1) return false; else { players = utils.removeElementAt(players, idx); //setObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD, players); removeObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD); utils.setResizeableBatchObjVar(master_object, VAR_PLAYERS_IN_BATTLEFIELD, players); return true; } } /*********************************************************************** * @brief Adds a player to the specified team * * @param obj_id player * @param string faction * @param obj_id master_object * * @return boolean *********************************************************************/ boolean addPlayerToTeam(obj_id player, string faction, obj_id master_object) { if (player == null || player == obj_id.NULL_ID) return false; if (master_object == null || master_object == obj_id.NULL_ID) return false; string player_faction = getPlayerTeamFaction(player); if (player_faction != null) return false; //obj_id[] participants_array = getParticipantsOnBattlefield(master_object); resizeable obj_id[] participants = new obj_id[0]; if (hasObjVar(master_object, battlefield.VAR_PARTICIPANTS)) participants = utils.getResizeableObjIdBatchObjVar(master_object, battlefield.VAR_PARTICIPANTS); int part_idx = utils.getElementPositionInArray(participants, player); if (part_idx == -1) participants = utils.addElement(participants, player); string[] factions_allowed = getStringArrayObjVar(master_object, VAR_FACTIONS_ALLOWED); int idx = utils.getElementPositionInArray(factions_allowed, faction); if (idx == -1) return false; utils.setResizeableBatchObjVar(master_object, VAR_PARTICIPANTS, participants); //setObjVar(master_object, VAR_PARTICIPANTS, participants); setObjVar(player, VAR_TEAM_FACTION, faction); // Suppress linting - Lint script is incorrectly // catching this due to a similarly named array if (movePlayerToStartLocation(player, master_object)) { LOG("LOG_CHANNEL", player + " ->You have been moved to your faction's starting location. Good luck!"); sendSystemMessageTestingOnly(player, "You have been moved to your faction's starting location. Good luck!"); sendSystemMessageTestingOnly(player, "Note: use /battlefieldStatus to check on your faction's progress and /placeBattlefieldStructure to build."); } // Register the player with the PVP Battlefield system region reg = getRegionFromMasterObject(master_object); pvpBattlefieldSetParticipant(player, reg, getFactionId(faction)); // Mark the player has having entered the battlefield. //setBattlefieldEntered(player, master_object); // Give the player any battlefield waypoints. //giveBattlefieldWaypoints(master_object, player); // Add the player to the all faction battlefield chatroom. dictionary params = new dictionary(); string chat_room = battlefield.getChatRoomNameAllFactions(master_object); params.put("chat_room", chat_room); messageTo(player, "msgJoinBattlefieldChat", params, 0.0f, false); // Add player to the team chat channel. No need to join a faction chat channel // if there's only one player faction. if (factions_allowed.length > 1) { dictionary params_team = new dictionary(); string chat_room_team = battlefield.getChatRoomNameFaction(master_object, faction); params_team.put("chat_room", chat_room_team); messageTo(player, "msgJoinBattlefieldChat", params_team, 0.0f, false); } sendFactionMessage(master_object, faction, getFirstName(player) + " has joined the team."); // Give the specific game script a chance to do something. dictionary params_player = new dictionary(); params_player.put("player", player); params_player.put("faction", faction); messageTo(master_object, "msgAddPlayerToBattlefield", params_player, 3.0f, false); LOG("LOG_CHANNEL", "battlefield::addPlayerToTeam -- added " + player); return true; } /*********************************************************************** * @brief Overload addPlayerToTeam * * @param obj_id player * @param string faction * @param region r * * @return boolean *********************************************************************/ boolean addPlayerToTeam(obj_id player, string faction, region r) { if (r == null) return false; obj_id master_object = getMasterObjectFromRegion(r); return addPlayerToTeam(player, faction, master_object); } /*********************************************************************** * @brief Moves a player to his faction's starting location * * @param obj_id player * @param obj_id master_object * * @return boolean *********************************************************************/ boolean movePlayerToStartLocation(obj_id player, obj_id master_object) { LOG("LOG_CHANNEL", "movePlayerToStartLocation --" + player + " " + master_object); if (player == null || player == obj_id.NULL_ID) return false; if (master_object == null || master_object == obj_id.NULL_ID) return false; string faction = getPlayerTeamFaction(player); location start_loc = getFactionStartLocation(master_object, faction); if (start_loc == null) return false; // Get a random location around the area. location rand_loc = utils.getRandomAwayLocation(start_loc, MIN_START_LOCATION_TOLERANCE, MAX_START_LOCATION_TOLERANCE); setLocation(player, rand_loc); return true; } /*********************************************************************** * @brief Expels the player from the battlefield * * @param obj_id player * @param obj_id master_object * * @return boolean *********************************************************************/ boolean expelPlayerFromBattlefield(obj_id player, obj_id master_object) { if (player == null || player == obj_id.NULL_ID) return false; if (master_object == null || master_object == obj_id.NULL_ID) return false; setObjVar(player, VAR_EXPELLED, 1); expelFromTriggerVolume(master_object, STRING_TRIG_OUTER_PERIMETER, player); return true; } /*********************************************************************** * @brief Expels the player from the battlefield * * @param obj_id player * * @return boolean *********************************************************************/ boolean removeFactionItems(obj_id player) { if (player == null || player == obj_id.NULL_ID) return false; // If the player is declared, he can keep his battlefield items equipped. int pvp_type = pvpGetType(player); if (pvp_type == PVPTYPE_DECLARED) return true; factions.unequipFactionEquipment(player, true); return true; } /*********************************************************************** * @brief Decrements or resets the battlefield timer * * @param obj_id master_object * @param boolean reset true decrements the timer at the pulse * interval. False resets it. * * @return int time remaining. 0 if time expired, -1 on error. *********************************************************************/ int setGameTimer(obj_id master_object, boolean reset) { if (master_object == null || master_object == obj_id.NULL_ID) return -1; if (reset) { int game_time = getGameDuration(master_object); setObjVar(master_object, VAR_TIME_REMAINING, game_time); return game_time; } else { if (hasObjVar(master_object, VAR_TIME_REMAINING)) { int time_remaining = getIntObjVar(master_object, VAR_TIME_REMAINING); time_remaining = time_remaining - GAME_TIME_PULSE; setObjVar(master_object, VAR_TIME_REMAINING, time_remaining); if (time_remaining < 1) return 0; else return time_remaining; } else return 0; } } /*********************************************************************** * @brief Marks the player as having entered the battlefield * * @param obj_id player * @param obj_id master_object * * @return boolean false on error *********************************************************************/ boolean setBattlefieldEntered(obj_id player, obj_id master_object) { if (player == null || player == obj_id.NULL_ID) return false; if (master_object == null || master_object == obj_id.NULL_ID) return false; setObjVar(player, VAR_BATTLEFIELD_ENTERED, master_object); setObjVar(player, VAR_TIME_ENTERED, getGameTime()); return true; } /*********************************************************************** * @brief Decrements a faction's build points * * @param obj_id master_object * @param string faction * @param int amt Amount to decrement * * @return boolean false on fail or insufficient amount *********************************************************************/ boolean decrementFactionBuildPoints(obj_id master_object, string faction, int amt) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (amt < 1) return false; int build_points = getFactionBuildPoints(master_object, faction); if (amt > build_points) return false; build_points = build_points - amt; string objVar_name = VAR_BUILD_POINTS + faction; setObjVar(master_object, objVar_name, build_points); return true; } /*********************************************************************** * @brief Increases a faction's build points * * @param obj_id master_object * @param string faction * @param int amt Amount to decrement * * @return boolean false on fail *********************************************************************/ boolean incrementFactionBuildPoints(obj_id master_object, string faction, int amt) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (amt < 1) return false; int build_points = getFactionBuildPoints(master_object, faction); if (build_points == -1) return false; build_points = build_points + amt; string objVar_name = VAR_BUILD_POINTS + faction; setObjVar(master_object, objVar_name, build_points); return true; } /*********************************************************************** * @brief Spends a player's faction points. * * @param obj_id player * @param float amt Amount to spend * * @return boolean false on fail or insufficient funds *********************************************************************/ boolean spendFactionPoints(obj_id player, float amt) { if (player == null || player == obj_id.NULL_ID) return false; if (amt < 1) return false; string faction = getPlayerTeamFaction(player); if (faction == null) return false; float points = factions.getFactionStanding(player, faction); // The player can never go below the faction minimum if declared. Treat that as the zero point. int declared_faction = pvpGetAlignedFaction(player); if (declared_faction != 0) points = points - factions.FACTION_RATING_DECLARABLE_MIN; if (amt > points) { LOG("LOG_CHANNEL", player + " ->You do not have enough faction points remaining."); sendSystemMessageTestingOnly(player, "You do not have enough faction points remaining."); if (declared_faction != 0) sendSystemMessageTestingOnly(player, "Note that your faction may not go below the " + factions.FACTION_RATING_DECLARABLE_MIN + " declared minimum."); return false; } else { factions.addFactionStanding(player, faction, amt * -1); return true; } } /*********************************************************************** * @brief Eliminates a team from the game. * * @param obj_id master_object * @param string faction * * @return boolean false on error *********************************************************************/ boolean eliminateFaction(obj_id master_object, string faction) { if (master_object == null || master_object == obj_id.NULL_ID) return false; string[] factions_remaining_array = getFactionsRemaining(master_object); resizeable string[] factions_remaining = factions_remaining_array; if (factions_remaining == null) return false; int idx = utils.getElementPositionInArray(factions_remaining, faction); if (idx == -1) { LOG("LOG_CHANNEL", "battlefield.eliminateFaction -- eliminate ai faction " + faction); // check the ai factions remaining. string[] ai_factions_array = getAIFactionsRemaining(master_object); resizeable string[] ai_factions = ai_factions_array; int ai_idx = utils.getElementPositionInArray(ai_factions, faction); if (ai_idx == -1) { LOG("LOG_CHANNEL", "battlefield::eliminateFaction -- cannot find " + faction + " in " + master_object); return false; } else { ai_factions = utils.removeElementAt(ai_factions, idx); if(ai_factions.length > 0) { // Zero length array check setObjVar(master_object, VAR_FACTIONS_AI_REMAINING, ai_factions); } else { if(hasObjVar(master_object, VAR_FACTIONS_AI_REMAINING)) { removeObjVar(master_object, VAR_FACTIONS_AI_REMAINING); } } // Remove the ai opponents of the faction. region bf = getRegionFromMasterObject(master_object); obj_id[] base_objects = pvpBattlefieldGetParticipantsForFaction(bf, 0); if (base_objects != null) { for (int i = 0; i < base_objects.length; i++) { // We only want to remove the spawned creatures. if (isBattlefieldSpawned(base_objects[i])) { // We don't use removeBattlefieldObject here. Spawned creatures // must be destroyed directly. They clean up themselves. destroyObject(base_objects[i]); } } } sendBattlefieldMessage(master_object, "The " + faction + " faction has been eliminated from the battle."); return true; } } else { LOG("LOG_CHANNEL", "battlefield.eliminateFaction -- eliminate player faction " + faction); // remove faction from faction remaining. factions_remaining = utils.removeElementAt(factions_remaining, idx); if(factions_remaining.length > 0) { setObjVar(master_object, VAR_FACTIONS_REMAINING, factions_remaining); } else { if(hasObjVar(master_object, VAR_FACTIONS_REMAINING)) { removeObjVar(master_object, VAR_FACTIONS_REMAINING); } } // Remove faction members from the battlefield. sendFactionMessage(master_object, faction, "Your faction has been eliminated from the battle."); obj_id[] faction_team = getFactionTeam(master_object, faction); if (faction_team != null) { for (int i = 0; i < faction_team.length; i++) expelPlayerFromBattlefield(faction_team[i], master_object); } sendBattlefieldMessage(master_object, "The " + faction + " faction has been eliminated from the battle."); return true; } } /*********************************************************************** * @brief Starts a new game * * @param obj_id master_object * * @return boolean *********************************************************************/ boolean startBattlefield(obj_id master_object) { LOG("LOG_CHANNEL", "Starting battlefield game for " + master_object); if (master_object == null || master_object == obj_id.NULL_ID) return false; setGameTimer(master_object, true); // Expel everyone inside the battlefield at the start of the game. obj_id[] players = getPlayersOnBattlefield(master_object); if (players != null) { for (int i = 0; i < players.length; i++) expelPlayerFromBattlefield(players[i], master_object); } // Create battlefield objects int idx = getBattlefieldIndex(master_object, BATTLEFIELD_DATATABLE); if (idx == -1) { LOG("LOG_CHANNEL", "battlefield::startBattlefield -- Unable to find the index for " + master_object); return false; } createBattlefieldObjects(master_object, idx); // Set all factions as remaining. string[] factions_allowed = getFactionsAllowed(master_object); if (factions_allowed != null && factions_allowed.length > 0) { // Zero length array check setObjVar(master_object, VAR_FACTIONS_REMAINING, factions_allowed); } string[] factions_ai = getAIFactionsAllowed(master_object); if (factions_ai != null && factions_ai.length > 0) { // Zero length array check setObjVar(master_object, VAR_FACTIONS_AI_REMAINING, factions_ai); } // Set starting build points for each faction. for (int i = 0; i < factions_allowed.length; i++) { string objVar_name = VAR_BUILD_POINTS + factions_allowed[i]; setObjVar(master_object, objVar_name, STARTING_BUILD_POINTS); } // Start the game time pulse. messageTo(master_object, "msgGameTimePulse", null, (int)GAME_TIME_PULSE, false); // Attach the game script to the battlefield object attachGameScript(master_object); return true; } /*********************************************************************** * @brief Ends the game, doing necessary clean-up. * * @param obj_id master_object * @param boolean restart whether or not to restart another game * * @return boolean *********************************************************************/ boolean endBattlefield(obj_id master_object, boolean restart) { LOG("LOG_CHANNEL", "Ending battlefield game for " + master_object); if (master_object == null || master_object == obj_id.NULL_ID) return false; // Send ending message to all participants. obj_id[] participants = getParticipantsOnBattlefield(master_object); if (participants != null) { region bf = getRegionFromMasterObject(master_object); for (int i = 0; i < participants.length; i++) { dictionary end_params = new dictionary(); string chatroom = getChatRoomNameAllFactions(master_object); end_params.put("chatroom", chatroom); int faction_id = pvpBattlefieldGetFaction(participants[i], bf); string faction = factions.getFactionNameByHashCode(faction_id); if (faction != null) { string chatroom_faction = getChatRoomNameFaction(master_object, faction); end_params.put("chatroom_faction", chatroom_faction); } end_params.put("master_object", master_object); messageTo(participants[i], "msgEndBattlefieldGame", end_params, 1.0f, true); } } // Clear game obj vars if (hasObjVar(master_object, VAR_GAME)) removeObjVar(master_object, VAR_GAME); // Stamp game end time setObjVar(master_object, VAR_NEXT_GAME, getGameTime()); // Clean up battlefield objects. destroyBaseObjects(master_object); //Remove everything from the battlefield PVP permissions. region reg = getRegionFromMasterObject(master_object); LOG("LOG_CHANNEL", "battlefield::endBattlefield -- reg ->" + reg); pvpBattlefieldClearParticipants(reg); // Send message for next game start if (restart) { int restart_min = getGameRestartMinimum(master_object); int restart_max = getGameRestartMaximum(master_object); int restart_time = rand(restart_min, restart_max); setObjVar(master_object, VAR_NEXT_GAME, getGameTime() + restart_time); messageTo(master_object, "msgStartGame", null, (float)restart_time, true); } else { // Setting next game to -9999 marks the battlefield as disabled. setObjVar(master_object, VAR_NEXT_GAME, -9999); } //Detach the game script from the battlefield object detachGameScript(master_object); return true; } /*********************************************************************** * @brief Overloaded for endBattlefield * * @param obj_id master_object * * @return boolean *********************************************************************/ boolean endBattlefield(obj_id master_object) { return endBattlefield(master_object, true); } /*********************************************************************** * @brief Creates objects and defines start locations within the battlefield * * @param obj_id master_object * @param int index datatable location to read the objects * * @return void *********************************************************************/ void createBattlefieldObjects(obj_id master_object, int idx) { int num_items = dataTableGetNumRows(BATTLEFIELD_DATATABLE); if (num_items > idx + 1) { // Look for objects immediately after the battlefield index //resizeable obj_id[] object_list = new obj_id[0]; for (int i = idx + 1; i < num_items; i++) { string bf_name = dataTableGetString(BATTLEFIELD_DATATABLE, i, DATATABLE_COL_NAME); // There are no more objects if the next battlefield is reached if (bf_name.length() > 0) return; string planet = getCurrentSceneName(); dictionary object_row = dataTableGetRow(BATTLEFIELD_DATATABLE, i); string obj_template = object_row.getString(DATATABLE_COL_OBJECT); float x = object_row.getFloat(DATATABLE_COL_OBJECT_X); float y = object_row.getFloat(DATATABLE_COL_OBJECT_Y); float z = object_row.getFloat(DATATABLE_COL_OBJECT_Z); int delta = object_row.getInt(DATATABLE_COL_OBJECT_DELTA); float heading = object_row.getFloat(DATATABLE_COL_HEADING); string faction = object_row.getString(DATATABLE_COL_FACTION); string structure_type = object_row.getString(DATATABLE_COL_STRUCTURE_TYPE); int game_critical = object_row.getInt(DATATABLE_COL_CRITICAL); string script = object_row.getString(DATATABLE_COL_SCRIPT); float value1 = object_row.getFloat(DATATABLE_COL_VALUE1); float value2 = object_row.getFloat(DATATABLE_COL_VALUE2); if (obj_template == "START_LOC") { // This is a start location for a faction int jidx = utils.getElementPositionInArray(getFactionsAllowed(master_object), faction); if (jidx != -1) { location faction_start; if (delta == 1) { location bf_loc = getLocation(master_object); faction_start = new location(bf_loc.x - x, bf_loc.y - y, bf_loc.z - z, planet); } else faction_start = new location(x, y, z, planet); location[] start_locations = getLocationArrayObjVar(master_object, VAR_START_LOCATIONS); if(start_locations != null && start_locations.length > 0) { // Zero length array check start_locations[jidx] = faction_start; setObjVar(master_object, VAR_START_LOCATIONS, start_locations); } } continue; } // Determine the object's location and create it location obj_loc; if (delta == 1) { // Use delta coordinates from the battlefield center. location bf_loc = getLocation(master_object); obj_loc = new location(bf_loc.x - x, bf_loc.y - y, bf_loc.z - z, planet); } else obj_loc = new location(x, y, z, planet); obj_id object = createObject(obj_template, obj_loc); //LOG("LOG_CHANNEL", "object ->" + object + " template ->" + obj_template); //LOG("LOG_CHANNEL", "...structure_type ->" + structure_type); if (obj_loc == null) LOG("LOG_CHANNEL", "Unable to create " + obj_template); else { if (heading != 0.0f); setYaw(object, heading); // Register the object with the battlefield region reg = getRegionFromMasterObject(master_object); int faction_id = getFactionId(faction); //LOG("LOG_CHANNEL", "... faction ->" + faction + "faction_id ->" + faction_id); if (faction_id != 0) pvpBattlefieldSetParticipant(object, reg, faction_id); // Check for special structure types if (structure_type.length() > 0) { if (structure_type.equals("healing")) { // This is a healing station. setObjVar(object, "healing.canhealwound", 1); } if (structure_type.startsWith("spawner")) { // This is a spawner. Spawner types are in the format "spawner_type" int spawn_idx = dataTableSearchColumnForString(structure_type, DATATABLE_COL_SPAWNER_TYPE, SPAWNER_DATATABLE); if (spawn_idx == -1) LOG("LOG_CHANNEL", "battlefield::createBattlefieldObjects -- Invalid spawner type for " + object + " in battlefield " + master_object); else { LOG("LOG_CHANNEL", "spawn_idx ->" + spawn_idx); dictionary spawn_row = dataTableGetRow(SPAWNER_DATATABLE, spawn_idx); string spawner_type = spawn_row.getString(DATATABLE_COL_SPAWNER_TYPE); int pulse = spawn_row.getInt(DATATABLE_COL_SPAWNER_PULSE); int spawner_max = spawn_row.getInt(DATATABLE_COL_SPAWNER_MAX_SPAWN); int population_max = spawn_row.getInt(DATATABLE_COL_SPAWNER_MAX_POPULATION); setObjVar(object, VAR_SPAWNER_TYPE, spawner_type); setObjVar(object, VAR_SPAWNER_PULSE, pulse); setObjVar(object, VAR_SPAWNER_MAX, spawner_max); setObjVar(object, VAR_SPAWNER_MAX_POPULATION, population_max); attachScript(object, SCRIPT_BATTLEFIELD_SPAWNER); // Set the spawner in motion. messageTo(object, "msgBattlefieldSpawn", null, pulse, false); } } } // Add objvars and scripts to game critical objects if (game_critical == 1) { setObjVar(object, VAR_GAME_CRITICAL, 1); if (value1 != 0.0f) setObjVar(object, VAR_VALUE1, value1); if (value2 != 0.0f) setObjVar(object, VAR_VALUE2, value2); if (script.length() > 0) { attachScript(object, script); } } //object_list = utils.addElement(object_list, object); // Battlefield object script goes on every non-crit attachScript(object, SCRIPT_BATTLEFIELD_OBJECT); //persistObject(object); } // Store the list of created objects on the structure //if (object_list.length > 0) //{ // setObjVar(master_object, VAR_BASE_OBJECTS, object_list); //} } } return; } /*********************************************************************** * @brief Starts the construction of a buildable object. * * @param obj_id master_object * @param obj_id player player that requested the construction * @param location where the structure is to be built * @param dictionary dictionary of buildable object stats * (in the format of getBuildableObjectStats) * * @return void *********************************************************************/ void startBuildingConstruction(obj_id master_object, obj_id player, location position, int rotation, dictionary stats) { LOG("LOG_CHANNEL", "battlefield::startBuildingConstruction --" + stats); if (master_object == null || master_object == obj_id.NULL_ID) return; string name = stats.getString("name"); int time = stats.getInt("construction_time"); string template = stats.getString("construction_template"); int cost = stats.getInt("cost"); float height = stats.getFloat("height"); float yaw = (float)(rotation * 90); region bf = getRegionFromMasterObject(master_object); int faction_id = pvpBattlefieldGetFaction(player, bf); string faction = factions.getFactionNameByHashCode(faction_id); int repair_cost = cost / 10; if (repair_cost < 1) repair_cost = 1; // Add the construction site to the battlefield obj_id structure = addBattlefieldObject(master_object, template, position, yaw, faction); LOG("LOG_CHANNEL", "structure ->" + structure + " template ->" + template); if (structure == null) return; // Set construction site objvars. setObjVar(structure, VAR_BUILDTIME, time); setObjVar(structure, VAR_TIMESTAMP, getGameTime()); setObjVar(structure, VAR_NAME, name); setObjVar(structure, VAR_REPAIR_COST, repair_cost); setObjVar(structure, VAR_HEIGHT, height); // Send a message on building completion. stats.put("player", player); messageTo(structure, "msgConstructionComplete", stats, time, true); // Send a faction message sendFactionMessage(master_object, faction, getFirstName(player) + " started construction on " + name); return; } /*********************************************************************** * @brief Creates a reinforcement and gives control of it to the * specified player. * * @param obj_id structure installation from which the reinforcement * is generated. * @param obj_id player * * @return obj_id reinforcement created *********************************************************************/ obj_id buildReinforcement(obj_id master_object, obj_id structure, obj_id player) { if (structure == null || structure == obj_id.NULL_ID) return null; if (player == null || player == obj_id.NULL_ID) return null; string template = getStringObjVar(structure, VAR_REINFORCEMENT_TEMPLATE); if (template == null) return null; string name = getStringObjVar(structure, VAR_REINFORCEMENT_NAME); float cost = getFloatObjVar(structure, VAR_REINFORCEMENT_COST); if (spendFactionPoints(player, cost)) { // Create the reinforcement location loc = getLocation(structure); location spawn_loc = utils.getRandomAwayLocation(loc, 5.0f, 10.0f); string faction = getPlayerTeamFaction(player); obj_id reinforcement = addBattlefieldMob(master_object, template, spawn_loc, faction); LOG("LOG_CHANNEL", "battlefield.buildReinforcement -- created " + reinforcement); // Make the reinforcement a pet of the player. pet_lib.makePet(reinforcement, player); pet_lib.setupDefaultCommands(reinforcement); // Mark it as battlefield constructed setObjVar(reinforcement, battlefield.VAR_CONSTRUCTED, 1); // Record last build time setObjVar(structure, battlefield.VAR_LAST_BUILD, getGameTime()); // send a message to the faction sendFactionMessage(master_object, faction, getName(player) + " has acquired a reinforcement " + name + "."); return reinforcement; } else return null; } /*********************************************************************** * @brief Intiates repairs in the specified structure. * * @param obj_id master_object * @param obj_id player player initiating the repair * @param obj_id structure structure to repair. * * @return boolean *********************************************************************/ boolean repairBattlefieldStructure(obj_id master_object, obj_id player, obj_id structure) { if (master_object == null || master_object == obj_id.NULL_ID) return false; if (structure == null || structure == obj_id.NULL_ID) return false; if (!hasScript(structure, SCRIPT_DESTRUCTIBLE_BUILDING) && !hasScript(structure, SCRIPT_DESTROY_OBJECTIVE)) { LOG("LOG_CHANNEL", player + " ->You cannot repair that."); sendSystemMessageTestingOnly(player, "You cannot repair that."); return false; } if (getHitpoints(structure) == getMaxHitpoints(structure)) { LOG("LOG_CHANNEL", player + " ->That does not need repairing."); sendSystemMessageTestingOnly(player, "That does not need repairing."); return false; } // Decrement build points by the repair cost. int repair_cost = getIntObjVar(structure, VAR_REPAIR_COST); string faction = getPlayerTeamFaction(player); if (decrementFactionBuildPoints(master_object, faction, repair_cost)) { // Start the repair loop. setObjVar(structure, VAR_REPAIRING, 1); messageTo(structure, "msgRepairPulse", null, REPAIR_PULSE, true); LOG("LOG_CHANNEL", player + " ->Repairs initiated."); sendSystemMessageTestingOnly(player, "Repairs initiated."); return true; } else { LOG("LOG_CHANNEL", player + " ->You do not have the " + repair_cost + " build points to initiate repair."); sendSystemMessageTestingOnly(player, "You do not have the " + repair_cost + " build points to initiate repair."); return false; } }