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

4049 lines
126 KiB
Plaintext

/**********************************************************************
* Title: battlefield.scriptlib
* Description: Library for battlefields
**********************************************************************/
/***** 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 = (location)start_locations[idx].clone();
// 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] = (location)faction_start.clone();
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;
}
}