Files
dsrc/sku.0/sys.server/compiled/game/script/guild/master_city_object.script
T
2013-09-10 23:17:15 -07:00

866 lines
28 KiB
Plaintext

// ======================================================================
//
// master_city_object.script
//
// Copyright 2003 Sony Online Entertainment
//
// ======================================================================
include library.city;
include library.prose;
include library.utils;
include library.money;
include library.xp;
include library.objvar_mangle;
include library.player_structure;
include library.debug;
//------------------------------------------------
// Constants
//------------------------------------------------
const int CITY_PROCESS_INTERVAL = 60*60; // 1 hour
const int CITY_UPDATE_INTERVAL = 60*60*24*7; // 1 week
const string_id ELECTION_INCUMBENT_WIN_SUBJECT = new string_id( "city/city", "election_incumbent_win_subject" );
const string_id ELECTION_INCUMBENT_WIN_BODY = new string_id( "city/city", "election_incumbent_win_body" );
const string_id ELECTION_INCUMBENT_LOST_SUBJECT = new string_id( "city/city", "election_incumbent_lost_subject" );
const string_id ELECTION_INCUMBENT_LOST_BODY = new string_id( "city/city", "election_incumbent_lost_body" );
const string_id ELECTION_NEW_MAYOR_SUBJECT = new string_id( "city/city", "election_new_mayor_subject" );
const string_id ELECTION_NEW_MAYOR_BODY = new string_id( "city/city", "election_new_mayor_body" );
const string_id CITY_EXPAND_SUBJECT = new string_id( "city/city", "city_expand_subject" );
const string_id CITY_EXPAND_BODY = new string_id( "city/city", "city_expand_body" );
const string_id CITY_CONTRACT_SUBJECT = new string_id( "city/city", "city_contract_subject" );
const string_id CITY_CONTRACT_BODY = new string_id( "city/city", "city_contract_body" );
const string_id CITY_INVALID_SUBJECT = new string_id( "city/city", "city_invalid_subject" );
const string_id CITY_INVALID_BODY = new string_id( "city/city", "city_invalid_body" );
const string_id CITY_EXPAND_CAP_SUBJECT = new string_id( "city/city", "city_expand_cap_subject" );
const string_id CITY_EXPAND_CAP_BODY = new string_id( "city/city", "city_expand_cap_body" );
const string_id PUBLIC_ELECTION_INC_SUBJECT = new string_id( "city/city", "public_election_inc_subject" );
const string_id PUBLIC_ELECTION_INC_BODY = new string_id( "city/city", "public_election_inc_body" );
const string_id PUBLIC_ELECTION_SUBJECT = new string_id( "city/city", "public_election_subject" );
const string_id PUBLIC_ELECTION_BODY = new string_id( "city/city", "public_election_body" );
const string_id SID_CITY_UPDATE_ETA = new string_id( "city/city", "city_update_eta" );
//------------------------------------------------
// OnInitialize
//------------------------------------------------
trigger OnInitialize()
{
messageTo(self, "onCityUpdatePulse", null, CITY_PROCESS_INTERVAL, false);
return SCRIPT_CONTINUE;
}
//------------------------------------------------
// onCityUpdatePulse
//------------------------------------------------
messageHandler onCityUpdatePulse()
{
CustomerServiceLog("player_city", "--- City Update ---");
// Update all cities.
updateCities(self, false);
// Queue next update.
messageTo(self, "onCityUpdatePulse", null, CITY_PROCESS_INTERVAL, false);
return SCRIPT_CONTINUE;
}
//------------------------------------------------
// updateCities
//------------------------------------------------
void updateCities(obj_id self, boolean force)
{
int[] cityUpdateIds = objvar_mangle.getMangledIntArrayObjVar(self, "cityUpdate.ids");
int[] cityUpdateTimes = objvar_mangle.getMangledIntArrayObjVar(self, "cityUpdate.times");
string strCityUpdateInterval = getConfigSetting("GameServer", "cityUpdateInterval");
int cityUpdateInterval = 0;
if(strCityUpdateInterval != null)
cityUpdateInterval = utils.stringToInt(strCityUpdateInterval);
if(cityUpdateInterval < CITY_PROCESS_INTERVAL)
cityUpdateInterval = CITY_UPDATE_INTERVAL;
int currentTime = getGameTime();
int nextTime = currentTime + cityUpdateInterval;
if(cityUpdateIds != null && cityUpdateTimes != null && cityUpdateIds.length == cityUpdateTimes.length)
{
// Process any pending city updates.
for(int i = 0; i < cityUpdateIds.length; ++i)
{
if(force || cityUpdateTimes[i] <= currentTime)
{
cityUpdateTimes[i] = nextTime;
cityUpdate(cityUpdateIds[i], self, cityUpdateInterval, true);
}
}
}
else
{
cityUpdateIds = null;
cityUpdateTimes = null;
}
// Update the city information to match all current cities.
int[] cityIds = getAllCityIds();
int[] newCityUpdateTimes = new int[cityIds.length];
for(int i = 0; i < cityIds.length; ++i)
{
int pos = findIntOffsetInTable(cityUpdateIds, cityIds[i]);
if(pos == -1)
newCityUpdateTimes[i] = nextTime;
else
newCityUpdateTimes[i] = cityUpdateTimes[pos];
}
objvar_mangle.setMangledIntArrayObjVar(self, "cityUpdate.ids", cityIds);
objvar_mangle.setMangledIntArrayObjVar(self, "cityUpdate.times", newCityUpdateTimes);
}
//------------------------------------------------
// forceUpdate
//------------------------------------------------
messageHandler forceUpdate()
{
// A god mode player has forced a city update.
int city_id = params.getInt("city_id");
int no_citizen_cleanup = params.getInt("no_citizen_cleanup");
cityUpdate(city_id, self, CITY_UPDATE_INTERVAL, (no_citizen_cleanup == 0));
return SCRIPT_CONTINUE;
}
//------------------------------------------------
// forceElection
//------------------------------------------------
messageHandler forceElection()
{
// A god mode player has forced a city election.
int city_id = params.getInt("city_id");
electMayor(city_id, self, CITY_UPDATE_INTERVAL);
return SCRIPT_CONTINUE;
}
//------------------------------------------------
// forceRank
//------------------------------------------------
messageHandler forceRank()
{
// A god mode player has forced a city rank change.
int city_id = params.getInt("city_id");
int rank_change = params.getInt("rank_change");
int rank = city.getCityRank(city_id) - 1;
if(rank_change > 0)
{
increaseRank(city_id, rank, true);
}
else if(rank_change < 0)
{
decreaseRank(city_id, rank);
}
return SCRIPT_CONTINUE;
}
//------------------------------------------------
// cityUpdate
//------------------------------------------------
void cityUpdate(int city_id, obj_id self, int interval, boolean cleanup)
{
// Do this city's weekly update.
obj_id cityHall = cityGetCityHall(city_id);
string name = cityGetName(city_id);
CustomerServiceLog("player_city", "Updating City: " + name + " (" + city_id + "/" + cityHall + ")");
// Tally mayoral votes and elect a new mayor.
int cityVoteInterval = getIntObjVar(self, "vote_interval." + city_id);
cityVoteInterval++;
if(cityVoteInterval == 3)
{
// Elect a new mayor every 3rd week.
electMayor(city_id, self, interval);
cityVoteInterval = 0;
}
setObjVar(self, "vote_interval." + city_id, cityVoteInterval);
dictionary outparams = new dictionary();
outparams.put("cityVoteInterval", cityVoteInterval);
if(!messageTo(cityHall, "setVoteInterval", outparams, 0.f, true))
{
//vote interval not updated - failed messageTo
CustomerServiceLog("player_city", "Updating City: Vote Interval not Updated - Should have been set to "+ cityVoteInterval +". City: " + name + " (" + city_id + "/" + cityHall + ")");
}
// Grant the mayor an xp bonus, since we want them to gain skills a bit faster than the 3 week voting cycle.
obj_id incumbent_mayor = cityGetLeader(city_id);
grantExperiencePoints(incumbent_mayor, xp.POLITICAL, 750);
// Check city radius.
validateCityRadius(city_id, self);
// Check civic structure cap.
checkCivicCap(city_id, self);
// Collect taxes.
collectTaxes(city_id, self);
// Perform city maintenance.
cityMaintenance(city_id, self);
// Clean up city intervals.
obj_var_list ovl = getObjVarList(self, "vote_interval");
if(ovl != null)
{
for(int i = 0; i < ovl.getNumItems(); i++)
{
obj_var ov = ovl.getObjVar(i);
string test_name = ov.getName();
int test_id = utils.stringToInt(test_name);
if(!cityExists(test_id))
{
removeObjVar(self, "vote_interval." + test_name);
}
}
}
// Clean up the citizen list.
/**** Removed until we figure out why citizens are being removed out of turn.
if ( cleanup )
cleanupCitizens( city_id, self );
****/
}
//------------------------------------------------
// electMayor
//------------------------------------------------
void electMayor(int city_id, obj_id self, int interval)
{
// Do this city's weekly election.
obj_id cityHall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "Election Cycle: " + city_name + " (" + city_id + "/" + cityHall + ")");
// Accumulate a list of who everyone is voting for.
resizeable obj_id[] vote_ids = new obj_id[0];
resizeable int[] vote_counts = new int[0];
obj_id[] citizens = cityGetCitizenIds(city_id);
if(citizens.length <= 0)
{
CustomerServiceLog("player_city", "Election Cycle for City: " + city_name + " (" + city_id + "/" + cityHall + ") INVALID Citizen Array - Allowing to continue momentarily");
}
for(int i = 0; i < citizens.length; i++)
{
if(!isIdValid(citizens[i]))
CustomerServiceLog("player_city", "Election Cycle for City: " + city_name + " (" + city_id + "/" + cityHall + "). Citizen: (" + citizens[i] + ") is Invalid.");
boolean found = false;
obj_id vote = cityGetCitizenAllegiance(city_id, citizens[i]);
//make sure the 'Vote' is actually a Citizen of the City at the
//time the elections calculate a winner.
if(isIdValid(vote) && city.isCitizenOfCity(vote, city_id))
{
for(int j = 0; (j < vote_ids.length); j++)
{
// Increment vote count for a person who has been voted for.
if(vote_ids[j] == vote)
{
vote_counts[j] = vote_counts[j] + 1;
found = true;
break;
}
}
if(!found)
{
// Person has not been voted for yet.
utils.addElement(vote_ids, vote);
utils.addElement(vote_counts, 1);
}
}
else
{
CustomerServiceLog("player_city", "Election Cycle for City: " + city_name + " (" + city_id + "/" + cityHall + "). Citizen: (" + citizens[i] + ") has 'Voted for/allegience to' an Invalid ID(" + vote + ") This vote won't count.");
}
}
// Figure out who earned the most votes.
obj_id incumbent_mayor = cityGetLeader(city_id);
obj_id new_mayor = null;
int max_votes = 0;
int incumbent_votes = 0;
int xp_granted = 0;
int csTotal = 0;
//no one voted - CS Log because a '***Null***' log will hit later
if(vote_ids.length == 0)
{
CustomerServiceLog("player_city", "Election Cycle: No one Voted in this election. City: " + city_name + " (" + city_id + "/" + cityHall + "). Incumbent will remain Mayor - ***NULL*** CS Log will be generated below.");
}
for(int i = 0; i < vote_ids.length; i++)
{
// Grant xp.
// Add obj_id validation to fix granting XP to no target bug
// We may in the future want to change this to a messageTo to verify that the
// receipient always gets his or her XP, even if they are offline
if(isIdValid(vote_ids[i]))
{
CustomerServiceLog("player_city", "Election Cycle: Player has recieved " + vote_counts[i] + " votes granting " + vote_counts[i] * 100 + " points of " + xp.POLITICAL + " XP for running in the " + city_name + " (" + city_id + "/" + cityHall + ") election. " + vote_ids[i]);
grantExperiencePoints(vote_ids[i], xp.POLITICAL, vote_counts[i] * 300);
xp_granted++;
}
else
{
CustomerServiceLog("player_city", "Election Cycle: Invalid ID ("+ vote_ids[i] +") has recieved " + vote_counts[i] + " votes in the City Election: " + city_name + " (" + city_id + "/" + cityHall + "). No Experience was granted due to Invalid ID.");
}
if(vote_ids[i] == incumbent_mayor)
incumbent_votes = vote_counts[i];
if(vote_counts[i] > max_votes)
{
max_votes = vote_counts[i];
new_mayor = vote_ids[i];
}
csTotal += vote_counts[i];
}
// if ( (vote_ids.length > 0) && (citizens.length != csTotal) )
// CustomerServiceLog("player_city", "XP Error for " + city_name + "("+ city_id + "/" + cityHall + "). There were " + citizens.length + " possible votes but only " + csTotal + " votes were counted for XP");
// If no one got any votes, retain the incumbent.
if(new_mayor == null)
{
CustomerServiceLog("player_city_transfer", "Incumbent Mayor ("+ incumbent_mayor +")"+ cityGetCitizenName(city_id, incumbent_mayor) +" Of City("+ city_id +")"+ cityGetName(city_id) +" Wins due to NEW MAYOR obj_id being - **** NULL **** - ");
new_mayor = incumbent_mayor;
}
boolean incumbent_win = false;
// Check for an incumbent win.
// Note that the incumbent wins all ties. Other ties are settled by whoever happens to be first in the list.
// The incumbent wins if the winner is already a mayor of another city.
if((new_mayor == incumbent_mayor) || (new_mayor == null) || (max_votes == incumbent_votes) || city.isAMayor(new_mayor))
{
// Keep the incumbent.
CustomerServiceLog("player_city", "Incumbent Win: " + incumbent_mayor + " Votes: " + incumbent_votes + " City: " + city_name + " (" + city_id + "/" + cityHall + ")");
// Notify the incumbent.
string imayor_name = cityGetCitizenName(city_id, incumbent_mayor);
prose_package bodypp = prose.getPackage(ELECTION_INCUMBENT_WIN_BODY, incumbent_mayor, city_name);
utils.sendMail(ELECTION_INCUMBENT_WIN_SUBJECT, bodypp, imayor_name, "City Hall");
incumbent_win = true;
}
else
{
CustomerServiceLog("player_city_transfer", "New Mayor: " + new_mayor + " Votes: " + max_votes + " City: " + city_name + " (" + city_id + "/" + cityHall + ")");
// Elect a new mayor.
city.setMayor( city_id, new_mayor );
// Notify the new mayor.
string nmayor_name = cityGetCitizenName(city_id, new_mayor);
prose_package bodypp = prose.getPackage(ELECTION_NEW_MAYOR_BODY, new_mayor, city_name);
utils.sendMail(ELECTION_NEW_MAYOR_SUBJECT, bodypp, nmayor_name, "City Hall");
// Notify the old mayor.
string imayor_name = cityGetCitizenName(city_id, incumbent_mayor);
bodypp = prose.getPackage(ELECTION_INCUMBENT_LOST_BODY, new_mayor, city_name);
utils.sendMail(ELECTION_INCUMBENT_LOST_SUBJECT, bodypp, imayor_name, "City Hall");
// Notify all structures of the new mayor.
// Civic structures will use this message to change their owner and admin references.
city.doMayoralStructureTransfer(new_mayor, incumbent_mayor, city_id);
}
// Reset all allegiance to null.
for(int i = 0; i < citizens.length; i++)
{
city.setCitizenAllegiance(city_id, citizens[i], null);
}
// Tell the city hall to wipe voting records.
dictionary outparams = new dictionary();
outparams.put("lastUpdateTime", getGameTime());
outparams.put("currentInterval", interval);
if(!messageTo(cityGetCityHall(city_id), "resetVoteTerminal", outparams, 0.f, true))
{
CustomerServiceLog("player_city_transfer", "ResetVotingTerminal for City ("+ city_id +") "+ cityGetName(city_id) +" FAILED - MessageTo Failed to send: Candidate List has not been removed properly.");
}
// Notify the public.
string nmayor_name = cityGetCitizenName(city_id, new_mayor);
for(int i = 0; i < citizens.length; i++)
{
string citizen_name = cityGetCitizenName(city_id, citizens[i]);
if(incumbent_win)
{
prose_package bodypp = prose.getPackage(PUBLIC_ELECTION_INC_BODY, city_name, nmayor_name);
utils.sendMail(PUBLIC_ELECTION_INC_SUBJECT, bodypp, citizen_name, "City Hall");
}
else
{
prose_package bodypp = prose.getPackage(PUBLIC_ELECTION_BODY, city_name, nmayor_name);
utils.sendMail(PUBLIC_ELECTION_SUBJECT, bodypp, citizen_name, "City Hall");
}
}
}
//------------------------------------------------
// validateCityRadius
//------------------------------------------------
void validateCityRadius(int city_id, obj_id self)
{
obj_id cityHall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "City Validation: " + city_name + " (" + city_id + "/" + cityHall + ")");
int[] radiusList = dataTableGetIntColumn(city.RANK_TABLE, city.RANK_RADIUS);
int[] popList = dataTableGetIntColumn(city.RANK_TABLE, city.RANK_POPULATION);
obj_id mayor = cityGetLeader(city_id);
string mayor_name = cityGetCitizenName(city_id, mayor);
// Get our current radius and population requirement.
int currentRadius = cityGetRadius(city_id);
int currentPopReq = 0;
int nextPopReq = 0;
int rank = 0;
for(int i = 0; i < popList.length; i++)
{
if(radiusList[i] == currentRadius)
{
rank = i;
currentPopReq = popList[i];
if(i + 1 < popList.length)
nextPopReq = popList[i + 1];
break;
}
}
// Get our current population.
obj_id[] citizens = cityGetCitizenIds(city_id);
// Check our status.
if(citizens.length < popList[0])
{
// We've fallen below the min citizen count to be valid.
rank = 0;
int newRadius = radiusList[rank];
dictionary params = new dictionary();
params.put("rank", rank);
params.put("radius", newRadius);
messageTo(cityHall, "contractCity", params, 0.f, true);
// Notify the mayor.
prose_package bodypp = prose.getPackage(CITY_INVALID_BODY, city_name, rank + 1);
utils.sendMail(CITY_INVALID_SUBJECT, bodypp, mayor_name, "City Hall");
// Force the city to revalidate.
messageTo(cityHall, "validateCity", null, 259200.f, true);
CustomerServiceLog("player_city", "City Below Min Citizen Requirement! Population: " + citizens.length + " City: " + city_name + " (" + city_id + "/" + cityHall + ")");
}
else if(citizens.length < currentPopReq)
{
// Our city has decreased in size.
// Godhacked cities with this objvar are exempt from deranking.
if(!hasObjVar(cityHall, city.OBJVAR_DERANK_EXEMPT))
decreaseRank(city_id, rank);
}
else if((nextPopReq > 0) && (citizens.length >= nextPopReq))
{
// Our city has increased in size.
increaseRank(city_id, rank);
}
else
{
CustomerServiceLog("player_city", "City: " + city_name + " (" + city_id + "/" + cityHall + ")" + " Rank: " + rank + " CITY POP: " + citizens.length + " POP REQ: " + currentPopReq + " NEXT REQ: " + nextPopReq);
}
}
//------------------------------------------------
// decreaseRank
//------------------------------------------------
void decreaseRank(int city_id, int rank)
{
obj_id cityHall = cityGetCityHall(city_id);
// Shouldn't hypothetically happen but a secondary check to prevent deranking of exempt cities.
if(hasObjVar(cityHall, city.OBJVAR_DERANK_EXEMPT))
return;
int[] radiusList = dataTableGetIntColumn(city.RANK_TABLE, city.RANK_RADIUS);
int[] popList = dataTableGetIntColumn(city.RANK_TABLE, city.RANK_POPULATION);
obj_id mayor = cityGetLeader(city_id);
string mayor_name = cityGetCitizenName(city_id, mayor);
string city_name = cityGetName(city_id);
rank--;
if(rank < 0)
rank = 0;
int newRadius = radiusList[rank];
CustomerServiceLog("player_city", "The city shrank. Rank: " + rank + " City: " + city_name + " (" + city_id + "/" + cityHall + ")");
// Tell the city hall to remove structures outside our new radius.
// Sent non-persistent as any structure loaded after will automatically remove itself from the city.
dictionary params = new dictionary();
params.put("rank", rank);
params.put("radius", newRadius);
messageTo(cityHall, "contractCity", params, 0.f, true);
// Notify the mayor.
prose_package bodypp = prose.getPackage(CITY_CONTRACT_BODY, city_name, rank + 1);
utils.sendMail(CITY_CONTRACT_SUBJECT, bodypp, mayor_name, "City Hall");
}
//------------------------------------------------
// increaseRank
//------------------------------------------------
void increaseRank(int city_id, int rank, boolean forced)
{
int[] radiusList = dataTableGetIntColumn(city.RANK_TABLE, city.RANK_RADIUS);
int[] popList = dataTableGetIntColumn(city.RANK_TABLE, city.RANK_POPULATION);
obj_id cityHall = cityGetCityHall(city_id);
obj_id mayor = cityGetLeader(city_id);
string mayor_name = cityGetCitizenName(city_id, mayor);
string city_name = cityGetName(city_id);
location our_loc = cityGetLocation(city_id);
string planet_name = our_loc.area;
rank++;
if(rank > city.RANK_MAX)
rank = city.RANK_MAX;
int newRadius = radiusList[rank];
int medium_city_limit = 0;
int big_city_limit = 0;
string[] planets = dataTableGetStringColumn("datatables/city/city_limits.iff", "SCENE");
for(int i = 0; i < planets.length; i++)
{
if(planets[i].equals(planet_name))
{
medium_city_limit = dataTableGetInt("datatables/city/city_limits.iff", i, "MEDIUM_CITY_LIMIT");
big_city_limit = dataTableGetInt("datatables/city/city_limits.iff", i, "BIG_CITY_LIMIT");
break;
}
}
// Check to see if we can increase rank.
if(rank == 2) // (rank 3, rank is zero based in this function)
{
// Are there X or more cities rank 3 or larger?
int mid_size_cities = 0;
int[] city_ids = getAllCityIds();
for(int i = 0; i < city_ids.length; i++)
{
location city_loc = cityGetLocation(city_ids[i]);
if(city_loc.area.equals(planet_name) && (city.getCityRank(city_ids[i]) >= 3))
mid_size_cities++;
}
if(!forced)
{
if(mid_size_cities >= medium_city_limit)
{
// We can't increase in size.
prose_package bodypp = prose.getPackage(CITY_EXPAND_CAP_BODY, city_name, rank + 1);
utils.sendMail(CITY_EXPAND_CAP_SUBJECT, bodypp, mayor_name, "Planetary Civic Authority");
return;
}
}
}
else if(rank == 3) // rank 4 (if we are becoming rank 5, its ok)
{
// Are there X or more cities rank 4 or 5?
int large_size_cities = 0;
int[] city_ids = getAllCityIds();
for(int i = 0; i < city_ids.length; i++)
{
location city_loc = cityGetLocation(city_ids[i]);
if(city_loc.area.equals(planet_name) && (city.getCityRank(city_ids[i]) >= 4))
large_size_cities++;
}
if(!forced)
{
if(large_size_cities >= big_city_limit)
{
// We can't increase in size.
prose_package bodypp = prose.getPackage(CITY_EXPAND_CAP_BODY, city_name, rank + 1);
utils.sendMail(CITY_EXPAND_CAP_SUBJECT, bodypp, mayor_name, "Planetary Civic Authority");
return;
}
}
}
CustomerServiceLog("player_city", "The city grew. Rank: " + rank + " City: " + city_name + " (" + city_id + "/" + cityHall + ")");
// Tell the city hall to add new structures within our new radius.
// Sent non-persistent as any structure loaded after will automatically add itself to the city.
dictionary params = new dictionary();
params.put("rank", rank);
params.put("radius", newRadius);
messageTo(cityHall, "expandCity", params, 0.f, true);
// Notify the mayor.
prose_package bodypp = prose.getPackage(CITY_EXPAND_BODY, city_name, rank + 1);
utils.sendMail(CITY_EXPAND_SUBJECT, bodypp, mayor_name, "City Hall");
}
void increaseRank(int city_id, int rank)
{
increaseRank(city_id, rank, false);
}
//------------------------------------------------
// collectTaxes
//------------------------------------------------
void collectTaxes(int city_id, obj_id self)
{
// Property tax is handled by the maintenance system.
// Travel tax is handled by the travel system.
// Sales tax is handled by the commodities system.
}
//------------------------------------------------
// cityMaintenance
//------------------------------------------------
void cityMaintenance(int city_id, obj_id self)
{
obj_id city_hall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "City Maintenance: " + city_name + " (" + city_id + "/" + city_hall + ")");
// Tell the city hall to pay maintenance.
messageTo(city_hall, "payMaintenance", null, 0.f, true);
}
//------------------------------------------------
// findIntOffsetInTable
//------------------------------------------------
int findIntOffsetInTable(int[] from, int find)
{
if(from != null)
for(int i = 0; i < from.length; ++i)
if(from[i] == find)
return i;
return -1;
}
//------------------------------------------------
// confirmCityRemoved
//------------------------------------------------
messageHandler confirmCityRemoved()
{
obj_id city_hall = params.getObjId("city_hall");
if(city_hall == null)
return SCRIPT_CONTINUE;
int city_id = findCityByCityHall(city_hall);
if(cityExists(city_id))
{
string city_name = cityGetName(city_id);
debug.debugAllMsg("PLAYER CITY", self, "A city continued to exist after its hall was deleted! Attempting to remove the city. City: " + city_id + " Hall: " + city_hall);
CustomerServiceLog("player_city", "A city continued to exist after its hall was deleted! Attempting to remove the city. City: " + city_name + " (" + city_id + "/" + city_hall + ")");
removeCity(city_id);
return SCRIPT_CONTINUE;
}
debug.debugAllMsg("PLAYER CITY", self, "City master object confirmed removal of city. City: " + city_id + " Hall: " + city_hall);
CustomerServiceLog("player_city", "City master object confirmed removal of city. City: " + " (" + city_id + "/" + city_hall + ")");
return SCRIPT_CONTINUE;
}
//------------------------------------------------
// reportUpdateEstimate
//------------------------------------------------
messageHandler reportUpdateEstimate()
{
obj_id player = params.getObjId("player");
int city_id = params.getInt("city_id");
int[] cityUpdateIds = objvar_mangle.getMangledIntArrayObjVar(self, "cityUpdate.ids");
int[] cityUpdateTimes = objvar_mangle.getMangledIntArrayObjVar(self, "cityUpdate.times");
if(cityUpdateIds != null && cityUpdateTimes != null && cityUpdateIds.length == cityUpdateTimes.length)
{
// Process any pending city updates.
for(int i = 0; i < cityUpdateIds.length; ++i)
{
if(cityUpdateIds[i] == city_id)
{
int curt = getGameTime();
int diff = cityUpdateTimes[i] - curt;
string time_remaining = player_structure.assembleTimeRemaining(player_structure.convertSecondsTime(diff));
if(time_remaining.equals("error"))
time_remaining = "Update Pending: Your city will update with the next server city pulse.";
dictionary outparams = new dictionary();
outparams.put("time_remaining", time_remaining);
messageTo(player, "displayCityUpdateTime", outparams, 0.f, false);
return SCRIPT_CONTINUE;
}
}
}
return SCRIPT_CONTINUE;
}
//------------------------------------------------
// checkCivicCap
//------------------------------------------------
void checkCivicCap(int city_id, obj_id self)
{
// Tell the city hall to pay maintenance.
obj_id city_hall = cityGetCityHall(city_id);
messageTo(city_hall, "checkCivicCap", null, 0.f, true);
}
//------------------------------------------------
// cleanupCitizens
//------------------------------------------------
void cleanupCitizens(int city_id, obj_id self)
{
// Get our current population.
obj_id mayor = cityGetLeader(city_id);
obj_id[] citizens = cityGetCitizenIds(city_id);
for(int i = 0; i < citizens.length; i++)
{
if(citizens[i] == mayor)
continue;
int flags = cityGetCitizenPermissions(city_id, citizens[i]);
if((flags & city.CP_ABSENT_WEEK_5) != 0)
{
// This person has been gone a while, remove them from the citizen list.
string mayor_name = cityGetCitizenName(city_id, mayor);
prose_package bodypp = prose.getPackage(city.LOST_INACTIVE_CITIZEN_BODY, cityGetCitizenName(city_id, citizens[i]));
utils.sendMail(city.LOST_INACTIVE_CITIZEN_SUBJECT, bodypp, mayor_name, "City Hall");
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
cityRemoveCitizen(city_id, citizens[i]);
CustomerServiceLog("player_city", "Removed citizen due to inactivity. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Citizen: " + citizens[i]);
continue;
}
else if((flags & city.CP_ABSENT_WEEK_4) != 0)
flags = flags | city.CP_ABSENT_WEEK_5;
else if((flags & city.CP_ABSENT_WEEK_3) != 0)
flags = flags | city.CP_ABSENT_WEEK_4;
else if((flags & city.CP_ABSENT_WEEK_2) != 0)
flags = flags | city.CP_ABSENT_WEEK_3;
else if((flags & city.CP_ABSENT_WEEK_1) != 0)
flags = flags | city.CP_ABSENT_WEEK_2;
else
flags = flags | city.CP_ABSENT_WEEK_1;
string citname = cityGetCitizenName(city_id, citizens[i]);
obj_id citall = cityGetCitizenAllegiance(city_id, citizens[i]);
citySetCitizenInfo(city_id, citizens[i], citname, citall, flags);
}
}