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

2678 lines
77 KiB
Plaintext

/**
* Title: city library
*/
//------------------------------------------------
// Includes
//------------------------------------------------
include library.player_structure;
include library.planetary_map;
include library.debug;
//------------------------------------------------
// Constants
//------------------------------------------------
// City Code Version
const int CITY_VERSION = 4;
// City Rank Datatable
const string RANK_TABLE = "datatables/city/city_rank.iff";
const string RANK_RADIUS = "RADIUS";
const string RANK_POPULATION = "POPULATION";
const string RANK_STRING = "STRING";
const int RANK_MIN = 0;
const int RANK_MAX = 4;
// Citizen Permissions
const int CP_CITIZEN = 0; // base citizen without any additional permission
const int CP_MILITIA = (1<<0);
const int CP_ABSENT_WEEK_1 = (1<<1);
const int CP_ABSENT_WEEK_2 = (1<<2);
const int CP_ABSENT_WEEK_3 = (1<<3);
const int CP_ABSENT_WEEK_4 = (1<<4);
const int CP_ABSENT_WEEK_5 = (1<<5);
const int CP_INACTIVE_PROTECTED = (1<<6); // protected from being removed as a citizen and structures marked packable due to inactivity
// Structure Flags
const int SF_PM_REGISTER = 1;
const int SF_COST_CITY_HALL = 2; // 5000 (datatable entry 1)
const int SF_COST_CITY_HI = 4; // 1000
const int SF_COST_CITY_MED = 8; // 500
const int SF_COST_CITY_LOW = 16; // 250 (datatable entry 4)
const int SF_MISSION_TERMINAL = 32;
const int SF_SKILL_TRAINER = 64;
const int SF_DECORATION = 128;
// BEGIN: City Hall ONLY flags.
// Must be synchronized with datatables/city/specializations.iff
const int SF_SPEC_SAMPLE_RICH = 256; /*Sample Rich*/
const int SF_SPEC_FARMING = 512; /*removed*/
const int SF_SPEC_INDUSTRY = 1024; /*Manufacturing Center*/
const int SF_SPEC_RESEARCH = 2048; /*Research Center*/
const int SF_SPEC_CLONING = 4096; /*Clone Lab*/
const int SF_SPEC_MISSIONS = 8192; /*Improved Job Market*/
const int SF_SPEC_ENTERTAINER = 16384; /*Entertainment Districtu*/
const int SF_SPEC_DOCTOR = 32768; /*removed*/
const int SF_SPEC_STRONGHOLD = 65536; /*removed*/
const int SF_SPEC_MASTER_MANUFACTURING = 131072; /*removed*/
const int SF_SPEC_MASTER_HEALING = 262144; /*removed*/
const int SF_SPEC_DECOR_INCREASE = 524288; /*Outdoor Enhancements*/
const int SF_SPEC_STORYTELLER = 1048576; /*Encore Performance*/
const int SF_SPEC_INCUBATOR = 2097152; /*incubation-BMs*/
const int SF_SPEC_UNKNOWN_6 = 4194304;
const int SF_REQUIRE_ZONE_RIGHTS = 8388608;
// END: City Hall ONLY flags.
const int SF_COST_CITY_GARDEN_SMALL = 16777216;
const int SF_COST_CITY_GARDEN_LARGE = 33554432;
const int SPECIAL_STRUCTURE = SF_MISSION_TERMINAL | SF_SKILL_TRAINER | SF_DECORATION;
const int PAY_STRUCTURE = SF_COST_CITY_HALL | SF_COST_CITY_HI | SF_COST_CITY_MED |
SF_COST_CITY_LOW | SF_COST_CITY_GARDEN_SMALL | SF_COST_CITY_GARDEN_LARGE;
const int SPEC_MASK = SF_SPEC_SAMPLE_RICH | SF_SPEC_FARMING | SF_SPEC_INDUSTRY | SF_SPEC_RESEARCH |
SF_SPEC_CLONING | SF_SPEC_MISSIONS | SF_SPEC_ENTERTAINER | SF_SPEC_DOCTOR |
SF_SPEC_STRONGHOLD | SF_SPEC_MASTER_MANUFACTURING | SF_SPEC_MASTER_HEALING |
SF_SPEC_DECOR_INCREASE | SF_SPEC_STORYTELLER | SF_SPEC_INCUBATOR;
// Maintenance costs.
const int CITY_MAINTENANCE_COSTS[] = {
2500, // The city hall cost is this * city rank.
7500, // Shuttleport.
2000, // Garden, med, most structures
150, // Small object
1000, // Garden, small
3000 // Garden, large
};
// Citizen Emails
const string_id NEW_CITY_STRUCTURE_SUBJECT = new string_id( "city/city", "new_city_structure_subject" );
const string_id NEW_CITY_STRUCTURE_BODY = new string_id( "city/city", "new_city_structure_body" );
const string_id NEW_CITY_STRUCTURE_OTHER_SUBJECT = new string_id( "city/city", "new_city_structure_other_subject" );
const string_id NEW_CITY_STRUCTURE_OTHER_BODY = new string_id( "city/city", "new_city_structure_other_body" );
const string_id NEW_CITY_CITIZEN_SUBJECT = new string_id( "city/city", "new_city_citizen_subject" );
const string_id NEW_CITY_CITIZEN_BODY = new string_id( "city/city", "new_city_citizen_body" );
const string_id NEW_CITY_CITIZEN_OTHER_SUBJECT = new string_id( "city/city", "new_city_citizen_other_subject" );
const string_id NEW_CITY_CITIZEN_OTHER_BODY = new string_id( "city/city", "new_city_citizen_other_body" );
const string_id LOST_CITIZEN_SUBJECT = new string_id( "city/city", "lost_citizen_subject" );
const string_id LOST_CITIZEN_BODY = new string_id( "city/city", "lost_citizen_body" );
const string_id LOST_CITY_CITIZEN_SUBJECT = new string_id( "city/city", "lost_city_citizen_subject" );
const string_id LOST_CITY_CITIZEN_BODY = new string_id( "city/city", "lost_city_citizen_body" );
const string_id LOST_INACTIVE_CITIZEN_SUBJECT = new string_id( "city/city", "lost_inactive_citizen_subject" );
const string_id LOST_INACTIVE_CITIZEN_BODY = new string_id( "city/city", "lost_inactive_citizen_body" );
const string_id STRUCTURE_VALID_SUBJECT = new string_id( "city/city", "structure_valid_subject" );
const string_id STRUCTURE_VALID_BODY = new string_id( "city/city", "structure_valid_body" );
const string_id STRUCTURE_INVALID_SUBJECT = new string_id( "city/city", "structure_invalid_subject" );
const string_id STRUCTURE_INVALID_BODY = new string_id( "city/city", "structure_invalid_body" );
const string_id STRUCTURE_DESTROYED_SUBJECT = new string_id( "city/city", "structure_destroyed_subject" );
const string_id STRUCTURE_DESTROYED_BODY = new string_id( "city/city", "structure_destroyed_body" );
const string_id STRUCTURE_DESTROYED_MAINT_SUBJECT = new string_id( "city/city", "structure_destroyed_maint_subject" );
const string_id STRUCTURE_DESTROYED_MAINT_BODY = new string_id( "city/city", "structure_destroyed_maint_body" );
const string_id STRUCTURE_REPAIRED_SUBJECT = new string_id( "city/city", "structure_repaired_subject" );
const string_id STRUCTURE_REPAIRED_BODY = new string_id( "city/city", "structure_repaired_body" );
const string_id STRUCTURE_DAMAGED_SUBJECT = new string_id( "city/city", "structure_damaged_subject" );
const string_id STRUCTURE_DAMAGED_BODY = new string_id( "city/city", "structure_damaged_body" );
const string_id INCOME_TAX_PAID_SUBJECT = new string_id( "city/city", "income_tax_paid_subject" );
const string_id INCOME_TAX_PAID_BODY = new string_id( "city/city", "income_tax_paid_body" );
const string_id INCOME_TAX_NOPAY_SUBJECT = new string_id( "city/city", "income_tax_nopay_subject" );
const string_id INCOME_TAX_NOPAY_BODY = new string_id( "city/city", "income_tax_nopay_body" );
const string_id INCOME_TAX_NOPAY_MAYOR_SUBJECT = new string_id( "city/city", "income_tax_nopay_mayor_subject" );
const string_id INCOME_TAX_NOPAY_MAYOR_BODY = new string_id( "city/city", "income_tax_nopay_mayor_body" );
const string_id SID_NOT_IN_CITY = new string_id("city/city", "not_in_city");
const string_id SID_MAYOR_RESIDENCE_CHANGE = new string_id("city/city", "mayor_residence_change");
const string_id SID_OVER_MAX_LIMIT = new string_id("city/city", "must_remove_decorations_or_structures");
const string CITY_SPECS = "datatables/city/specializations.iff";
//zoning rights
const string_id SID_NO_RIGHTS = new string_id("player_structure", "no_transfer_rights");
// Reserved city names.
const string RESERVED_CITY_NAMES[] = {
"bela vistal",
"coronet",
"doaba guerfel",
"kor vella",
"tyrena",
"vreni island",
"dee'ja peak",
"deeja peak",
"keren",
"kadaara",
"kaadara",
"moenia",
"theed",
"narmle",
"restuss",
"dearic",
"daeric",
"nashal",
"anchorhead",
"bestine",
"mos eisley",
"mos espa",
"mos entha",
"mos taike",
"wayfar",
"lake retreat"
};
// Special objvar present on city hall prevents city from de-ranking. For God Mode h4xX0ring cities to remain a certain rank.
const string OBJVAR_DERANK_EXEMPT = "city.derank_exempt";
const string CITIZEN_LIST_QUERIED = "cityhall.citizen_list_queried";
const string CITIZEN_LIST_DATA = "cityhall.citizen_list_data";
//------------------------------------------------
// Functions
//------------------------------------------------
//------------------------------------------------
// canBuildCityHere
//
// Checks city proximity.
//------------------------------------------------
int canBuildCityHere(obj_id player, location loc)
{
int[] all_cities = getAllCityIds();
for(int i = 0; i < all_cities.length; i++)
{
location other_loc = cityGetLocation(all_cities[i]);
if(other_loc.area.equals(loc.area))
{
float dist = utils.getDistance2D(loc, other_loc);
if(dist < 1100)
return all_cities[i];
}
}
return -1;
}
//------------------------------------------------
// isInCity
//
// Return true if the structure is in a city.
//------------------------------------------------
boolean isInCity(obj_id obj)
{
return isInCity(getLocation(obj));
}
boolean isInCity(location loc)
{
int city_id = 0;
if(isIdValid(loc.cell))
loc = getLocation(getTopMostContainer(loc.cell));
city_id = getCityAtLocation(loc, 0);
if(cityExists(city_id))
return true;
else
return false;
}
//------------------------------------------------
// isPartOfCity
//
// Check whether we are part of a given city.
//------------------------------------------------
boolean isPartOfCity(obj_id structure, int city_id)
{
if(!isIdValid(structure))
return false;
obj_id[] city_structures = cityGetStructureIds(city_id);
if(city_structures == null)
return false;
for(int i = 0; i < city_structures.length; i++)
{
if(city_structures[i] == structure)
return true;
}
return false;
}
//------------------------------------------------
// isAMayor
//------------------------------------------------
boolean isAMayor(obj_id player)
{
int[] cities = getAllCityIds();
for(int i = 0; i < cities.length; i++)
{
obj_id mayor = cityGetLeader(cities[i]);
if(mayor == player)
return true;
}
return false;
}
//------------------------------------------------
// isTheCityMayor
//------------------------------------------------
boolean isTheCityMayor(obj_id player, int city_id)
{
obj_id mayor = cityGetLeader(city_id);
return mayor == player;
}
//------------------------------------------------
// getCityRank
//------------------------------------------------
int getCityRank(int city_id)
{
if(!cityExists(city_id))
return 0;
int rad = cityGetRadius(city_id);
int[] radList = dataTableGetIntColumn(city.RANK_TABLE, city.RANK_RADIUS);
int rank = 0;
for(int i = 0; i < radList.length; i++)
{
if(rad >= radList[i])
rank++;
}
return rank;
}
//------------------------------------------------
// addStructureToCity
//
// Add the given structure to the city it is located in.
//------------------------------------------------
boolean addStructureToCity(obj_id structure)
{
if(!isIdValid(structure))
return false;
// Check and make sure this isn't a temporary structure.
if(hasScript(structure, player_structure.SCRIPT_TEMPORARY_STRUCTURE))
return false;
int city_id = getCityAtLocation(getLocation(structure), 0);
if((city_id > 0) && (!isIdValid(getContainedBy(structure))))
return addStructureToCity(structure, city_id);
else
return false;
}
boolean addStructureToCity(obj_id structure, int city_id)
{
// Are we a member of this city already?
if(!isPartOfCity(structure, city_id))
{
boolean city_reg = isCityRegistered(city_id);
int flags = 0;
if(city_reg)
{
flags |= SF_PM_REGISTER;
messageTo(structure, "cityMapRegister", null, 0.f, false);
}
// Find out what our cost flag is.
int cost = player_structure.getStructureCityCost(structure);
if(cost > 0)
{
switch (cost)
{
case 1:
flags |= SF_COST_CITY_HALL;
break;
case 2:
flags |= SF_COST_CITY_HI;
break;
case 3:
flags |= SF_COST_CITY_MED;
break;
case 4:
flags |= SF_COST_CITY_LOW;
break;
case 5:
flags |= SF_COST_CITY_GARDEN_SMALL;
break;
case 6:
flags |= SF_COST_CITY_GARDEN_LARGE;
break;
}
}
// We are located inside a city, but not a member, so add us to it.
citySetStructureInfo(city_id, structure, flags, true);
// Track our city_id.
setStructureCityId(structure, city_id);
// OPTIONAL BEGIN
// Send a mail to the mayor.
obj_id mayor = cityGetLeader(city_id);
string mayor_name = cityGetCitizenName(city_id, mayor);
string structure_name = localize(getNameStringId(structure));
prose_package bodypp = prose.getPackage(NEW_CITY_STRUCTURE_BODY, structure_name, player_structure.getStructureOwner(structure));
utils.sendMail(NEW_CITY_STRUCTURE_SUBJECT, bodypp, mayor_name, "City Hall");
// Send a mail to the structure owner.
string city_name = cityGetName(city_id);
bodypp = prose.getPackage(NEW_CITY_STRUCTURE_OTHER_BODY, mayor_name, structure_name, city_name);
utils.sendMail(NEW_CITY_STRUCTURE_OTHER_SUBJECT, bodypp, player_structure.getStructureOwner(structure), "City Hall");
// OPTIONAL END
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Added structure to city. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Structure: " + structure);
// Is this structure a residence?
if(hasObjVar(structure, player_structure.VAR_RESIDENCE_BUILDING))
{
// Add the resident as a citizen.
obj_id resident = getObjIdObjVar(structure, player_structure.VAR_RESIDENCE_BUILDING);
addCitizen(resident, structure);
}
return true;
}
else
{
// Correct the building city id.
if(getStructureCityId(structure) != city_id)
setStructureCityId(structure, city_id);
}
return false;
}
//------------------------------------------------
// removeStructureFromCity
//
// Remove the given structure from the city it is located in.
//------------------------------------------------
boolean removeStructureFromCity(obj_id structure)
{
if(!isIdValid(structure))
return false;
// if ( !structure.isLoaded() )
// return false;
int city_id = getCityAtLocation(getLocation(structure), 0);
if(city_id > 0)
return removeStructureFromCity(city_id, structure);
return false;
}
boolean removeStructureFromCity(int city_id, obj_id structure)
{
// Are we a member of this city?
if(isPartOfCity(structure, city_id))
{
// We are located in a city.
cityRemoveStructure(city_id, structure);
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Removed structure from city. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Structure: " + structure);
// If this was a residence, remove the citizen.
if(hasObjVar(structure, player_structure.VAR_RESIDENCE_BUILDING))
{
obj_id resident = getObjIdObjVar(structure, player_structure.VAR_RESIDENCE_BUILDING);
obj_id mayor = cityGetLeader(city_id);
if(resident != mayor)
removeCitizen(resident, structure);
}
if(player_structure.isCivic(structure))
{
// Unregister us with the city map.
detachScript(structure, "planet_map.map_loc_both");
}
else
{
// Remove the structure city id on all structures except civic buildings.
// We don't remove the city id from civic buildings, because it may be needed when they are destroyed and cleaned up.
setStructureCityId(structure, 0);
}
return true;
}
else
return false;
}
//------------------------------------------------
// validateCityStructure
//
// Check to see if we need to be added to or removed from a city.
// Called when a structure is initialized (loaded).
// Also called in structure maintenance.
//------------------------------------------------
void validateCityStructure(obj_id structure)
{
if(!isIdValid(structure))
return;
int city_id = getCityAtLocation(getLocation(structure), 0);
int oldCity = getStructureCityId(structure);
if(oldCity > 0)
{
if(oldCity == city_id)
{
// We loaded into our current city.
// Do nothing.
}
else if((oldCity != city_id) && (city_id > 0))
{
// We were in a city, but we loaded into a different one.
CustomerServiceLog("player_city", "Structure validated in a different city. Old City ID: " + oldCity + " New City ID: " + city_id + " Structure: " + structure);
// Remove us from our old city.
if(cityExists(oldCity))
cityRemoveStructure(oldCity, structure);
// Destroy us if we are civic.
// Civic structures should only be in their original city.
if(player_structure.isCivic(structure))
{
player_structure.destroyStructure(structure);
return;
}
else
{
// Add us to the new city.
if(!isIdValid(getContainedBy(structure)))
{
addStructureToCity(structure, city_id);
setStructureCityId(structure, city_id);
}
}
}
else if(city_id == 0)
{
// We were in a city, but we loaded into no city.
//CustomerServiceLog( "player_city", "Structure validated in no city. Old City ID: " + oldCity + " Structure: " + structure );
CustomerServiceLog("player_city", "Structure validated in no city. Old City ID: " + oldCity + " Structure: " + structure);
// Remove us from our old city.
if(cityExists(oldCity))
cityRemoveStructure(oldCity, structure);
// Remove registration script.
if(hasScript(structure, "planet_map.map_loc_both"))
detachScript(structure, "planet_map.map_loc_both");
// Destroy us if we are civic.
if(player_structure.isCivic(structure))
{
player_structure.destroyStructure(structure);
return;
}
}
}
else
{
// Destroy us if we are civic.
// This needs to be enabled in the next publish.
/*
if ( player_structure.isCivic( structure ) )
{
player_structure.destroyStructure( structure );
return;
}
else
{ */
if(city_id > 0)
{
if(!isIdValid(getContainedBy(structure)))
{
// We weren't in a city and we loaded into one.
CustomerServiceLog("player_city", "Structure validated in new city. New City ID: " + city_id + " Structure: " + structure);
addStructureToCity(structure, city_id);
}
}
else
{
// We weren't in a city and we didn't load into one.
// Do nothing.
}
// }
}
// Check to see if this city can own this structure.
checkStructureValid(city_id, structure);
// Update registration script.
city.updateRegistrationScript(city_id, structure);
}
//------------------------------------------------
// validateSpecialStructure
//------------------------------------------------
boolean validateSpecialStructure(obj_id structure)
{
if(!isIdValid(structure))
return false;
int city_id = checkCity(structure, false);
int oldCity = getIntObjVar(structure, "city_id"); // specials must use the obj var
if(isNormalStructure(city_id, structure))
return false;
if(oldCity > 0)
{
if(oldCity == city_id)
{
// We loaded into our current city.
// Do nothing.
}
else if((oldCity != city_id) && (city_id > 0))
{
// We were in a city, but we loaded into a different one.
CustomerServiceLog("player_city", "Special object loaded into a different city. Old City ID: " + oldCity + " New City ID: " + city_id + " Object: " + structure);
destroyObject(structure);
return false;
}
else if(city_id == 0)
{
// We were in a city, but we loaded into no city.
CustomerServiceLog("player_city", "Special object loaded into no city. Old City ID: " + oldCity + " Object: " + structure);
destroyObject(structure);
return false;
}
}
else
{
CustomerServiceLog("player_city", "Special object loaded outside a city. Removing object. Object: " + structure);
destroyObject(structure);
return false;
}
// Check to see if this city can own this structure.
return checkStructureValid(city_id, structure);
}
//------------------------------------------------
// isCitizenOfCity
//
// Check to see if the given person is a citizen of our city.
//------------------------------------------------
boolean isCitizenOfCity(obj_id player, int city_id)
{
if(!cityExists(city_id))
return false;
obj_id[] citizens = cityGetCitizenIds(city_id);
if(citizens == null)
return false;
for(int i = 0; i < citizens.length; i++)
{
if(citizens[i] == player)
return true;
}
return false;
}
//------------------------------------------------
// isMilitiaOfCity
//------------------------------------------------
boolean isMilitiaOfCity(obj_id player, int city_id)
{
if(!cityExists(city_id))
return false;
obj_id[] citizens = cityGetCitizenIds(city_id);
if(citizens == null)
return false;
for(int i = 0; i < citizens.length; i++)
{
if((citizens[i] == player) && hasMilitiaFlag(player, city_id))
return true;
}
return false;
}
boolean hasMilitiaFlag(obj_id player, int city_id)
{
if(!cityExists(city_id))
return false;
if(!isIdValid(player))
return false;
int flags = cityGetCitizenPermissions(city_id, player);
if(0 != (flags & CP_MILITIA))
return true;
return false;
}
//------------------------------------------------
// addCitizen
//
// Add the given citizen to the city his residence resides in.
//------------------------------------------------
void addCitizen(obj_id citizen, obj_id residence)
{
if(!isIdValid(residence))
return;
if(!isIdValid(citizen) || !citizen.isLoaded())
return;
string citizen_name = getName(citizen);
if(citizen_name == null)
return;
int city_id = getCityAtLocation(getLocation(residence), 0);
if(!cityExists(city_id))
return;
if(isCitizenOfCity(citizen, city_id))
return;
obj_id mayor = cityGetLeader(city_id);
if(citizen == mayor)
return;
citySetCitizenInfo(city_id, citizen, citizen_name, null, CP_CITIZEN);
removeObjVar(citizen, "city.income_tax_time");
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Added citizen to city. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Citizen: " + citizen + " Residence: " + residence);
// Remove their city ban flag if they have one.
removeBan(citizen, city_id);
// Send a mail to the mayor.
string mayor_name = cityGetCitizenName(city_id, mayor);
prose_package bodypp = prose.getPackage(NEW_CITY_CITIZEN_BODY, citizen_name);
utils.sendMail(NEW_CITY_CITIZEN_SUBJECT, bodypp, mayor_name, "City Hall");
// Send a mail to the citizen.
string cname = cityGetCitizenName(city_id, citizen);
bodypp = prose.getPackage(NEW_CITY_CITIZEN_OTHER_BODY, mayor_name, citizen_name, city_name);
utils.sendMail(NEW_CITY_CITIZEN_OTHER_SUBJECT, bodypp, cname, "City Hall");
}
//------------------------------------------------
// removeCitizen
//
// Remove the given citizen from the city his residence resides in.
//------------------------------------------------
void removeCitizen(obj_id citizen, obj_id residence)
{
if(!isIdValid(residence))
return;
int city_id = getCityAtLocation(getLocation(residence), 0);
removeCitizen(citizen, city_id, residence);
}
//------------------------------------------------
// removeCitizen
//
// Remove the given citizen from the city his residence resides in.
//------------------------------------------------
void removeCitizen(obj_id citizen, int city_id, obj_id residence)
{
if(!cityExists(city_id))
return;
obj_id mayor = cityGetLeader(city_id);
if(citizen == mayor)
return;
// Check to see if we are a citizen of the city.
if(!isCitizenOfCity(citizen, city_id))
return;
//If the player was protected by the Mayor to avoid City House Packup - remove his Safe Flag.
if(hasMayorProtectionFlag(citizen, city_id))
{
removeSafeHouseCitizen(city_id, citizen);
}
string citizen_name = cityGetCitizenName(city_id, citizen);
if(citizen_name == null)
return;
// Send a mail to the mayor.
string mayor_name = cityGetCitizenName(city_id, mayor);
prose_package bodypp = prose.getPackage(LOST_CITY_CITIZEN_BODY, cityGetCitizenName(city_id, citizen));
utils.sendMail(LOST_CITY_CITIZEN_SUBJECT, bodypp, mayor_name, "City Hall");
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
cityRemoveCitizen(city_id, citizen);
if(isIdValid(residence))
CustomerServiceLog("player_city", "Removed citizen from city. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Citizen: " + citizen + " Residence: " + residence);
else
CustomerServiceLog("player_city", "Removed citizen from city. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Citizen: " + citizen + " Residence: (none specified)");
}
//------------------------------------------------
// addMilitia
//------------------------------------------------
void addMilitia(int city_id, obj_id citizen)
{
obj_id mayor = cityGetLeader(city_id);
int flags = cityGetCitizenPermissions(city_id, citizen);
flags = flags | CP_MILITIA;
//get the Citizen's Allegiance - we don't want his vote to change or be rejected because of changing status.
obj_id cit_all = cityGetCitizenAllegiance(city_id, citizen);
citySetCitizenInfo(city_id, citizen, cityGetCitizenName(city_id, citizen), cit_all, flags);
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Added militia. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Citizen: " + citizen);
// ADD: Send them mail.
}
//------------------------------------------------
// removeMilitia
//------------------------------------------------
void removeMilitia(int city_id, obj_id citizen)
{
obj_id mayor = cityGetLeader(city_id);
int flags = cityGetCitizenPermissions(city_id, citizen);
flags = flags & ~CP_MILITIA;
//get the Citizen's Allegiance - we don't want his vote to change or be rejected because of changing status.
obj_id cit_all = cityGetCitizenAllegiance(city_id, citizen);
citySetCitizenInfo(city_id, citizen, cityGetCitizenName(city_id, citizen), cit_all, flags);
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Removed militia. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Citizen: " + citizen);
// ADD: Send them mail.
}
//------------------------------------------------
// setCityResidence
//
// Add the given citizen to the city his new residence resides in.
//------------------------------------------------
void setCityResidence(obj_id citizen, obj_id newresidence)
{
// If we are a mayor of either city, we don't change city residence.
int new_city = getCityAtLocation(getLocation(newresidence), 0);
int old_city = getCitizenOfCityId(citizen);
// don't need to do anything if not changing city
if(old_city == new_city)
{
return;
}
obj_id new_mayor = cityGetLeader(new_city);
obj_id old_mayor = cityGetLeader(old_city);
if((new_mayor == citizen) || (old_mayor == citizen))
{
sendSystemMessage(citizen, SID_MAYOR_RESIDENCE_CHANGE);
return;
}
// First, remove them from their old city.
removeCitizen(citizen, old_city, null);
// Now add them to the new city (if one exists).
addCitizen(citizen, newresidence);
}
//------------------------------------------------
// setMayor
//------------------------------------------------
void setMayor(int city_id, obj_id new_mayor)
{
citySetLeader(city_id, new_mayor);
}
//------------------------------------------------
// setRadius
//------------------------------------------------
void setRadius(int city_id, int new_radius)
{
citySetRadius(city_id, new_radius);
}
//------------------------------------------------
// setName
//------------------------------------------------
void setName(int city_id, string new_name)
{
citySetName(city_id, new_name);
}
//------------------------------------------------
// setCitizenAllegiance
//------------------------------------------------
void setCitizenAllegiance(int city_id, obj_id citizen, obj_id new_allegiance)
{
citySetCitizenInfo(city_id, citizen, cityGetCitizenName(city_id, citizen), new_allegiance, cityGetCitizenPermissions(city_id, citizen));
}
//------------------------------------------------
// addStarport
//------------------------------------------------
boolean addStarport(obj_id shuttleport, location cityTravelLoc, int cityTravelCost, boolean cityTravelIntp)
{
int city_id = getCityAtLocation(getLocation(shuttleport), 0);
if(!cityExists(city_id))
return false;
int travelTax = cityGetTravelCost(city_id);
if(travelTax > 0)
cityTravelCost = travelTax;
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Adding starport. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Structure: " + shuttleport);
citySetTravelInfo(city_id, cityTravelLoc, cityTravelCost, cityTravelIntp);
return true;
}
//------------------------------------------------
// removeStarport
//------------------------------------------------
boolean removeStarport(obj_id shuttleport)
{
// Get the city id off the structure, in case we are outside the city.
int city_id = getStructureCityId(shuttleport);
if(!cityExists(city_id))
return false;
return removeStarport(shuttleport, city_id);
}
boolean removeStarport(obj_id shuttleport, int city_id)
{
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Removing starport. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Structure: " + shuttleport);
citySetTravelInfo(city_id, new location(), 0, false);
return true;
}
boolean addGarage(string template)
{
return true;
} //end addGarage
void removeGarage(obj_id structure)
{
return;
}
//------------------------------------------------
// isUniqueCityName
//------------------------------------------------
boolean isUniqueCityName(string newName)
{
int[] city_ids = getAllCityIds();
if(city_ids == null || city_ids.length == 0)
return true;
for(int i = 0; i < city_ids.length; i++)
{
string city_name = cityGetName(city_ids[i]);
if(city_name == newName)
return false;
}
// Match against the reserved names.
string lowerNewName = newName.toLowerCase();
for(int i = 0; i < RESERVED_CITY_NAMES.length; i++)
{
if(lowerNewName.indexOf(RESERVED_CITY_NAMES[i]) >= 0)
return false;
}
return true;
}
//------------------------------------------------
// isCityBanned
//------------------------------------------------
boolean isCityBanned(obj_id player, int city_id)
{
if(!cityExists(city_id))
return false;
int[] bannedIds = getIntArrayObjVar(player, "city.banlist");
if(bannedIds == null)
return false;
for(int i = 0; i < bannedIds.length; i++)
{
if(bannedIds[i] == city_id)
return true;
}
return false;
}
boolean isCityBanned(obj_id player, obj_id structure)
{
int city_id = getCityAtLocation(getLocation(structure), 0);
return isCityBanned(player, city_id);
}
//------------------------------------------------
// removeBan
//------------------------------------------------
boolean removeBan(obj_id player, int city_id)
{
if(!cityExists(city_id))
return false;
int[] banCities = getIntArrayObjVar(player, "city.banlist");
if(banCities == null)
return false;
int found = 0;
for(int i = 0; i < banCities.length; i++)
{
if(banCities[i] == city_id)
{
found = 1;
break;
}
}
if(found == 0)
return false;
if(banCities.length == 1)
{
removeObjVar(player, "city.banlist");
}
else
{
int j = 0;
int[] newBanCities = new int[banCities.length - 1];
for(int i = 0; i < banCities.length; i++)
{
if(banCities[i] != city_id)
{
newBanCities[j] = banCities[i];
j++;
}
}
setObjVar(player, "city.banlist", newBanCities);
}
return true;
}
//------------------------------------------------
// removeTaxesSetRadius
//
// Called during city contraction to set the radius and remove taxes for low rank cities in a batch operation.
//------------------------------------------------
void removeTaxesSetRadius(int city_id, int new_radius)
{
citySetIncomeTax(city_id, 0);
citySetPropertyTax(city_id, 0);
citySetSalesTax(city_id, 0);
// This should not normally happen, but adding in a check to fix script exception problems
if(new_radius < 1)
{
CustomerServiceLog("player_city", "ERROR: Attempted to set city radius of " + cityGetName(city_id) + " (City ID: " + city_id + ") to " + new_radius + "! Setting it to 150 instead");
new_radius = 150;
}
citySetRadius(city_id, new_radius);
}
//------------------------------------------------
// removeTaxes
//------------------------------------------------
void removeTaxes(int city_id)
{
removeTaxesSetRadius(city_id, cityGetRadius(city_id));
}
//------------------------------------------------
// setIncomeTax
//------------------------------------------------
void setIncomeTax(int city_id, int new_tax)
{
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Changed income tax. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Value: " + new_tax);
citySetIncomeTax(city_id, new_tax);
}
//------------------------------------------------
// setPropertyTax
//------------------------------------------------
void setPropertyTax(int city_id, int new_tax)
{
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Changed property tax. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Value: " + new_tax);
citySetPropertyTax(city_id, new_tax);
}
//------------------------------------------------
// setSalesTax
//------------------------------------------------
void setSalesTax(int city_id, int new_tax)
{
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Changed sales tax. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Value: " + new_tax);
citySetSalesTax(city_id, new_tax);
}
//------------------------------------------------
// setTravelFee
//------------------------------------------------
void setTravelFee(int city_id, int new_fee)
{
location cityTravelLoc = cityGetTravelLocation(city_id);
int cityTravelCost = new_fee;
boolean cityTravelIntp = cityGetTravelInterplanetary(city_id);
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Changed travel fee. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Value: " + new_fee);
citySetTravelInfo(city_id, cityTravelLoc, cityTravelCost, cityTravelIntp);
}
//------------------------------------------------
// setGarageFee
//------------------------------------------------
void setGarageFee(int city_id, int new_fee)
{
int garageUseCost = new_fee;
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
string garageCity = city_name + ".garageFee";
setObjVar(city_hall, garageCity, garageUseCost);
}
//------------------------------------------------
// setCloneInfo
//------------------------------------------------
void setCloneInfo(int city_id, location cityCloneLoc, location cityCloneRespawn, obj_id cityCloneId)
{
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Changed clone info. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Clone Loc: " + cityCloneLoc + " Id: " + cityCloneId);
citySetCloneInfo(city_id, cityCloneLoc, cityCloneRespawn, cityCloneId);
}
//------------------------------------------------
// updateLocation
//------------------------------------------------
void updateLocation(int city_id, location new_loc)
{
obj_id cityHall = cityGetCityHall(city_id);
location cityLoc = (location)new_loc.clone();
citySetLocation(city_id, new_loc);
}
//------------------------------------------------
// getPropertyTax
//------------------------------------------------
int getPropertyTax(obj_id structure)
{
int city_id = getCityAtLocation(getLocation(structure), 0);
if(cityExists(city_id))
return cityGetPropertyTax(city_id);
return 0;
}
//------------------------------------------------
// getCityHall
//------------------------------------------------
obj_id getCityHall(obj_id structure)
{
int city_id = getCityAtLocation(getLocation(structure), 0);
if(cityExists(city_id))
return cityGetCityHall(city_id);
return null;
}
//------------------------------------------------
// setStructureType
//------------------------------------------------
void setStructureType(int city_id, obj_id structure, int structureType)
{
boolean structureValid = cityGetStructureValid(city_id, structure);
citySetStructureInfo(city_id, structure, structureType, structureValid);
}
//------------------------------------------------
// setStructureValid
//------------------------------------------------
void setStructureValid(int city_id, obj_id structure, boolean structureValid)
{
int structureType = cityGetStructureType(city_id, structure);
citySetStructureInfo(city_id, structure, structureType, structureValid);
}
//------------------------------------------------
// isCityRegistered
//------------------------------------------------
boolean isCityRegistered(int city_id)
{
if(!cityExists(city_id))
return false;
obj_id hall = cityGetCityHall(city_id);
int flags = cityGetStructureType(city_id, hall);
if(0 != (flags & SF_PM_REGISTER))
return true;
else
return false;
}
//------------------------------------------------
// registerCity
//------------------------------------------------
void registerCity(int city_id)
{
if(!cityExists(city_id))
return;
obj_id[] structures = cityGetStructureIds(city_id);
for(int i = 0; i < structures.length; i++)
{
if(!isNormalStructure(city_id, structures[i]))
continue;
// Set our registration flag.
int flags = cityGetStructureType(city_id, structures[i]);
flags |= city.SF_PM_REGISTER;
setStructureType(city_id, structures[i], flags);
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Registered city on planetary map. City: " + city_name + " (" + city_id + "/" + city_hall + ")");
// Tell us to register now (if we are loaded).
messageTo(structures[i], "cityMapRegister", null, 0.f, false);
}
}
//------------------------------------------------
// unregisterCity
//------------------------------------------------
void unregisterCity(int city_id)
{
if(!cityExists(city_id))
return;
obj_id[] structures = cityGetStructureIds(city_id);
for(int i = 0; i < structures.length; i++)
{
if(!isNormalStructure(city_id, structures[i]))
continue;
// Turn off registration flag.
int flags = cityGetStructureType(city_id, structures[i]);
flags = flags & ~city.SF_PM_REGISTER;
setStructureType(city_id, structures[i], flags);
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Unregistered city from planetary map. City: " + city_name + " (" + city_id + "/" + city_hall + ")");
// Tell us to register now (if we are loaded).
messageTo(structures[i], "cityMapUnregister", null, 0.f, false);
}
}
//------------------------------------------------
// updateRegistrationScript
//
// Called by every structure's OnInitialize.
//------------------------------------------------
void updateRegistrationScript(int city_id, obj_id structure)
{
if(!cityExists(city_id))
return;
if(!player_structure.isCivic(structure))
return;
int flags = cityGetStructureType(city_id, structure);
if(0 != (flags & city.SF_PM_REGISTER))
{
// Add the script.
if(!hasScript(structure, "planet_map.map_loc_both"))
attachScript(structure, "planet_map.map_loc_both");
}
else
{
// Remove the script.
if(hasScript(structure, "planet_map.map_loc_both"))
detachScript(structure, "planet_map.map_loc_both");
}
}
//------------------------------------------------
// checkStructureValid
//------------------------------------------------
boolean checkStructureValid(int city_id, obj_id structure)
{
return checkStructureValid(city_id, structure, getCityRank(city_id));
}
boolean checkStructureValid(int city_id, obj_id structure, int city_rank)
{
// Check for special non-structures...
if(!isNormalStructure(city_id, structure))
return checkSpecialValid(city_id, structure, city_rank);
// Only apply to civic structures.
if(!player_structure.isCivic(structure))
return false;
if(!cityExists(city_id))
{
// Destroy this structure.
// This should never happen.
player_structure.destroyStructure(structure);
return false;
}
obj_id mayor = cityGetLeader(city_id);
string mayor_name = cityGetCitizenName(city_id, mayor);
string structure_name = localize(getNameStringId(structure));
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
// Check the rank.
boolean valid = cityGetStructureValid(city_id, structure);
int rank_req = player_structure.getStructureCityRank(structure);
if(city_rank < rank_req)
{
// We can't afford this structure!
if(valid)
{
// Make the structure invalid and notify the mayor.
setStructureValid(city_id, structure, false);
prose_package bodypp = prose.getPackage(STRUCTURE_INVALID_BODY, structure_name, mayor_name);
utils.sendMail(STRUCTURE_INVALID_SUBJECT, bodypp, mayor_name, "City Hall");
// Time stamp it.
setObjVar(structure, "city.invalid_timestamp", getGameTime());
CustomerServiceLog("player_city", "City can't support valid structure. Marking structure invalid. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Structure: " + structure);
}
else
{
// Make sure a week has passed.
int invalid_time = getIntObjVar(structure, "city.invalid_timestamp");
if(invalid_time == 0)
{
// No timestamp! Set one and delete us next time.
setObjVar(structure, "city.invalid_timestamp", getGameTime());
return true;
}
int cur_time = getGameTime();
if(cur_time - invalid_time < 7 * 24 * 60 * 60) // 1 week.
{
// Don't allow it to be destroyed yet.
return true;
}
// Destroy the structure and notify the mayor.
CustomerServiceLog("player_city", "City destroying invalid structure that can't be supported. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Structure: " + structure);
player_structure.destroyStructure(structure);
prose_package bodypp = prose.getPackage(STRUCTURE_DESTROYED_BODY, structure_name, mayor_name);
utils.sendMail(STRUCTURE_DESTROYED_SUBJECT, bodypp, mayor_name, "City Hall");
}
}
else
{
// We can afford this structure.
if(!valid)
{
// Make the structure valid and notify the mayor.
setStructureValid(city_id, structure, true);
prose_package bodypp = prose.getPackage(STRUCTURE_VALID_BODY, structure_name, mayor_name);
utils.sendMail(STRUCTURE_VALID_SUBJECT, bodypp, mayor_name, "City Hall");
CustomerServiceLog("player_city", "Invalid structure is now valid. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Structure: " + structure);
}
}
return true;
}
//------------------------------------------------
// checkSpecialValid
//------------------------------------------------
boolean checkSpecialValid(int city_id, obj_id structure)
{
return checkSpecialValid(city_id, structure, getCityRank(city_id));
}
boolean checkSpecialValid(int city_id, obj_id structure, int rank)
{
obj_id mayor = cityGetLeader(city_id);
string mayor_name = cityGetCitizenName(city_id, mayor);
string structure_name = localize(getNameStringId(structure));
obj_id city_hall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
// See if we are over the new count.
int curc = 0, maxc = 0;
string varstring = null;
if(isMissionTerminal(city_id, structure))
{
varstring = "city.mt_count";
curc = getMTCount(city_id) - utils.getIntScriptVar(city_hall, varstring);
maxc = getMaxMTCount(city_id, rank);
}
else if(isSkillTrainer(city_id, structure))
{
varstring = "city.st_count";
curc = getTrainerCount(city_id) - utils.getIntScriptVar(city_hall, varstring);
maxc = getMaxTrainerCount(city_id, rank);
}
else if(isDecoration(city_id, structure))
{
varstring = "city.deco_count";
curc = getDecorationCount(city_id) - utils.getIntScriptVar(city_hall, varstring);
maxc = getMaxDecorationCount(city_id, rank);
}
if(curc > maxc)
{
// We are over the count, remove us.
CustomerServiceLog("player_city", "Destroying special because it is over our max allowed count. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Object: " + structure);
prose_package bodypp = prose.getPackage(STRUCTURE_DESTROYED_BODY, structure_name, mayor_name);
utils.sendMail(STRUCTURE_DESTROYED_SUBJECT, bodypp, mayor_name, "City Hall");
if(isSkillTrainer(city_id, structure))
removeSkillTrainer(structure);
else
destroyObject(structure);
utils.setScriptVar(city_hall, varstring, utils.getIntScriptVar(city_hall, varstring) + 1);
return false;
}
else
return true;
}
//------------------------------------------------
// getStructureCost
//
// WARNING: Structure MAY NOT be loaded during this call.
//------------------------------------------------
int getStructureCost(int city_id, obj_id structure)
{
if(!cityExists(city_id))
return 0;
if(getConfigSetting("GameServer", "disableStructureFees") != null)
return 0;
int structureType = cityGetStructureType(city_id, structure);
if(0 != (structureType & SF_COST_CITY_HALL))
{
int cost = 1000 + CITY_MAINTENANCE_COSTS[0] * getCityRank(city_id);
// Add registration fee.
if(isCityRegistered(city_id))
cost += 5000;
// Add over cap fee.
int civic_count = city.getCivicCount(city_id);
int max_civic = city.getMaxCivicCount(city_id);
int diff = civic_count - max_civic;
if(diff > 0)
{
// Have we paid this penalty before?
if(hasObjVar(structure, "city.civic_cap_penalty"))
cost += 75000 * diff;
else
setObjVar(structure, "city.civic_cap_penalty", 1);
}
else if(hasObjVar(structure, "city.civic_cap_penalty"))
removeObjVar(structure, "city.civic_cap_penalty");
return cost;
}
else if(0 != (structureType & SF_COST_CITY_HI))
return CITY_MAINTENANCE_COSTS[1];
else if(0 != (structureType & SF_COST_CITY_MED))
return CITY_MAINTENANCE_COSTS[2];
else if(0 != (structureType & SF_COST_CITY_LOW))
return CITY_MAINTENANCE_COSTS[3];
else if(0 != (structureType & SF_COST_CITY_GARDEN_SMALL))
return CITY_MAINTENANCE_COSTS[4];
else if(0 != (structureType & SF_COST_CITY_GARDEN_LARGE))
return CITY_MAINTENANCE_COSTS[5];
else
return 0;
}
//------------------------------------------------
// initCitizen
//------------------------------------------------
void initCitizen(obj_id citizen)
{
// Check to see if we need to pay city membership tax ("income tax").
int city_id = getCitizenOfCityId(citizen);
if(!cityExists(city_id))
return;
obj_id mayor = cityGetLeader(city_id);
string mayor_name = cityGetCitizenName(city_id, mayor);
// Mayor doesn't have to pay.
if(citizen == mayor)
return;
// Clear city absence flags.
city.clearAbsenceFlags(citizen, city_id);
// Do we need to pay tax?
int last_tax_time = getIntObjVar(citizen, "city.income_tax_time");
int cur_time = getGameTime();
if(last_tax_time > 0)
{
// Check to see if time has passed.
if(cur_time - last_tax_time < 7 * 24 * 60 * 60) // one week
{
// Don't pay taxes yet.
return;
}
}
// Time to pay taxes.
setObjVar(citizen, "city.income_tax_time", cur_time);
string citizen_name = cityGetCitizenName(city_id, citizen);
obj_id city_hall = cityGetCityHall(city_id);
int income_tax = cityGetIncomeTax(city_id);
if(income_tax <= 0)
return;
if(!money.pay(citizen, city_hall, income_tax, "", null, false))
{
// Couldn't pay.
// Notify player.
prose_package bodypp = prose.getPackage(INCOME_TAX_NOPAY_BODY, citizen_name, income_tax);
utils.sendMail(INCOME_TAX_NOPAY_SUBJECT, bodypp, citizen_name, "City Hall");
// Notify mayor.
bodypp = prose.getPackage(INCOME_TAX_NOPAY_MAYOR_BODY, citizen_name, income_tax);
utils.sendMail(INCOME_TAX_NOPAY_MAYOR_SUBJECT, bodypp, mayor_name, "City Hall");
setObjVar(citizen, "city.income_tax_delinquent", 1);
}
else
{
// Notify player.
prose_package bodypp = prose.getPackage(INCOME_TAX_PAID_BODY, citizen_name, income_tax);
utils.sendMail(INCOME_TAX_PAID_SUBJECT, bodypp, citizen_name, "City Hall");
removeObjVar(citizen, "city.income_tax_delinquent");
}
}
//------------------------------------------------
// getCivicCount
//
// Civic structure count.
//------------------------------------------------
int getCivicCount(int city_id)
{
int count = 0;
obj_id[] structures = cityGetStructureIds(city_id);
for(int i = 0; i < structures.length; i++)
{
if(isPayStructure(city_id, structures[i]) && isNormalStructure(city_id, structures[i]))
count++;
}
return count;
}
//------------------------------------------------
// getMaxCivicCount
//
// Max allowed number of civic structures in this city.
//------------------------------------------------
int getMaxCivicCount(int city_id)
{
return getMaxCivicCount(city_id, getCityRank(city_id));
}
int getMaxCivicCount(int city_id, int rank)
{
//original MaxCivic was rank * 6, gave 50% increase in Update 8.
//added specialization that added another 50% increase in Update 8.
int baseCivicCount = (1 + (rank * 9));
//get the flag the city has set.
int flag = cityGetSpec(city_id);
if(flag == SF_SPEC_DECOR_INCREASE)
{
LOG("sissynoid", "City Has Increased Decoration Spec! Increasing Civic Structures by 10%");
//give them a 25% boost if they have the specialization
baseCivicCount = (1 + (rank * 12));
return baseCivicCount;
}
return baseCivicCount;
}
//------------------------------------------------------------------------------------------------
// MISSION TERMINALS
//------------------------------------------------------------------------------------------------
//------------------------------------------------
// getMTCount
//
// Mission terminal count.
//------------------------------------------------
int getMTCount(int city_id)
{
int count = 0;
obj_id[] structures = cityGetStructureIds(city_id);
for(int i = 0; i < structures.length; i++)
{
int flags = cityGetStructureType(city_id, structures[i]);
if(0 != (flags & SF_MISSION_TERMINAL))
count++;
}
return count;
}
//------------------------------------------------
// getMaxMTCount
//
// Max allowed number of mission terminals in this city.
//------------------------------------------------
int getMaxMTCount(int city_id)
{
return getMaxMTCount(city_id, getCityRank(city_id));
}
int getMaxMTCount(int city_id, int rank)
{
return rank * 3;
}
//------------------------------------------------
// addMissionTerminal
//------------------------------------------------
void addMissionTerminal(int city_id, obj_id player, string template)
{
if(!cityExists(city_id))
return;
// Create the terminal.
float yaw = getYaw(player);
obj_id mt = createObject(template, getLocation(player));
setYaw(mt, yaw);
attachScript(mt, "terminal.terminal_city_mission");
// Add this to our structure tracking.
int flags = SF_COST_CITY_LOW | SF_MISSION_TERMINAL;
citySetStructureInfo(city_id, mt, flags, true);
setObjVar(mt, "city_id", city_id); // Suppress linting - lint script incorrectly catches this
persistObject(mt);
obj_id city_hall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "Adding mission terminal. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Object: " + mt);
}
//------------------------------------------------
// removeMissionTerminal
//------------------------------------------------
void removeMissionTerminal(obj_id terminal)
{
// Find the city this is in.
int city_id = checkCity(terminal, false);
if(!cityExists(city_id))
return;
// Remove it from structure tracking.
cityRemoveStructure(city_id, terminal);
obj_id city_hall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "Removing mission terminal. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Object: " + terminal);
}
//------------------------------------------------------------------------------------------------
// SKILL TRAINERS
//------------------------------------------------------------------------------------------------
//------------------------------------------------
// getTrainerCount
//------------------------------------------------
int getTrainerCount(int city_id)
{
int count = 0;
obj_id[] structures = cityGetStructureIds(city_id);
for(int i = 0; i < structures.length; i++)
{
int flags = cityGetStructureType(city_id, structures[i]);
if(0 != (flags & SF_SKILL_TRAINER))
count++;
}
return count;
}
//------------------------------------------------
// getMaxTrainerCount
//------------------------------------------------
int getMaxTrainerCount(int city_id)
{
return getMaxTrainerCount(city_id, getCityRank(city_id));
}
int getMaxTrainerCount(int city_id, int rank)
{
return 0;
}
//------------------------------------------------
// addSkillTrainer
//------------------------------------------------
void addSkillTrainer(int city_id, obj_id player, string template)
{
if(!cityExists(city_id))
return;
// Create the terminal.
float yaw = getYaw(player);
obj_id st = createObject(template, getLocation(player));
setYaw(st, yaw);
setObjVar(st, "creator", player);
// attachScript( st, "terminal.terminal_city_mission" );
// Add this to our structure tracking.
int flags = SF_COST_CITY_LOW | SF_SKILL_TRAINER;
citySetStructureInfo(city_id, st, flags, true);
setObjVar(st, "city_id", city_id); // Suppress linting - lint script incorrectly catches this
obj_id city_hall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "Adding skill trainer. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Object: " + st);
}
//------------------------------------------------
// removeSkillTrainer
//------------------------------------------------
void removeSkillTrainer(obj_id trainer)
{
// Find the city this is in.
int city_id = checkCity(trainer, false);
if(!cityExists(city_id))
return;
// Remove it from structure tracking.
cityRemoveStructure(city_id, trainer);
obj_id city_hall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "Removing skill trainer. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Object: " + trainer);
}
//------------------------------------------------------------------------------------------------
// DECORATIONS
//------------------------------------------------------------------------------------------------
//------------------------------------------------
// getDecorationCount
//------------------------------------------------
int getDecorationCount(int city_id)
{
int count = 0;
obj_id[] structures = cityGetStructureIds(city_id);
for(int i = 0; i < structures.length; i++)
{
int flags = cityGetStructureType(city_id, structures[i]);
if(0 != (flags & SF_DECORATION))
count++;
}
return count;
}
//------------------------------------------------
// getMaxDecorationCount
//------------------------------------------------
int getMaxDecorationCount(int city_id)
{
return getMaxDecorationCount(city_id, getCityRank(city_id));
}
int getMaxDecorationCount(int city_id, int rank)
{
//original decoration was rank * 10, gave 50% increase in Update 8.
//added specialization that added another 50% increase in Update 8.
int baseDecorCount = rank * 15;
//get the flag the city has set.
int flag = cityGetSpec(city_id);
if(flag == SF_SPEC_DECOR_INCREASE)
{
LOG("sissynoid", "City Has Increased Decoration Spec! Increasing Decorations by 20%");
//give them a 25% boost if they choose the specialization
baseDecorCount = rank * 20;
return baseDecorCount;
}
return baseDecorCount;
}
//------------------------------------------------
// addDecoration
//------------------------------------------------
void addDecoration(int city_id, obj_id player, obj_id deco)
{
if(!cityExists(city_id))
return;
// Add this to our structure tracking.
int flags = SF_COST_CITY_LOW | SF_DECORATION;
citySetStructureInfo(city_id, deco, flags, true);
setObjVar(deco, "city_id", city_id); // Suppress linting - lint script incorrectly catches this
obj_id city_hall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "Adding decoration. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Object: " + deco);
}
//------------------------------------------------
// removeDecoration
//------------------------------------------------
void removeDecoration(obj_id deco)
{
// Find the city this is in.
int city_id = checkCity(deco, false);
if(!cityExists(city_id))
return;
// Remove it from structure tracking.
cityRemoveStructure(city_id, deco);
obj_id city_hall = cityGetCityHall(city_id);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "Removing decoration. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Object: " + deco);
}
//------------------------------------------------------------------------------------------------
// SPECIALIZATION
//------------------------------------------------------------------------------------------------
//------------------------------------------------
// setSpecialization
//------------------------------------------------
void setSpecialization(int city_id, string spec)
{
if(spec == null || spec.length() <= 0)
{
return;
}
if(spec.equals("city_spec_decor_increase"))
{
//check decoration and civic structure count.
//you can not remove the Outdoor Enhancements Spec if you are over your limit.
int rank = getCityRank(city_id);
int maxBaseDec = rank * 15;
int maxBaseCiv = 1 + (rank * 9);
if(getDecorationCount(city_id) > maxBaseDec || getCivicCount(city_id) > maxBaseCiv)
{
obj_id mayor = cityGetLeader(city_id);
sendSystemMessage(mayor, SID_OVER_MAX_LIMIT);
return;
}
}
obj_id city_hall = cityGetCityHall(city_id);
// Clear any existing spec.
int type = cityGetStructureType(city_id, city_hall);
type = type & ~SPEC_MASK;
if(spec.equals("null"))
{
setStructureType(city_id, city_hall, type);
return; // Cleared the spec.
}
int flag = 0;
string[] specs = dataTableGetStringColumn(CITY_SPECS, "SPECIALIZATION");
for(int i = 0; i < specs.length; i++)
{
if(specs[i].equals(spec))
{
flag = dataTableGetInt(CITY_SPECS, i, "BIT");
break;
}
}
if(flag == 0)
return; // Couldn't find the bit to set.
// Set the spec flag.
type |= flag;
setStructureType(city_id, city_hall, type);
string city_name = cityGetName(city_id);
LOG("sissynoid", "Setting specialization. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Spec: " + spec);
CustomerServiceLog("player_city", "Setting specialization. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Spec: " + spec);
}
//------------------------------------------------
// cityHasSpec
//------------------------------------------------
boolean cityHasSpec(int city_id, int spec_bit)
{
if(city_id <= 0)
return false;
obj_id city_hall = cityGetCityHall(city_id);
int flags = cityGetStructureType(city_id, city_hall);
return (0 != (flags & spec_bit));
}
//------------------------------------------------
// cityGetSpec
//------------------------------------------------
int cityGetSpec(int city_id)
{
obj_id city_hall = cityGetCityHall(city_id);
int flags = cityGetStructureType(city_id, city_hall);
return flags & SPEC_MASK;
}
//------------------------------------------------
// cityGetSpecString
//------------------------------------------------
string cityGetSpecString(int city_id)
{
int spec = cityGetSpec(city_id);
int[] bits = dataTableGetIntColumn(CITY_SPECS, "BIT");
for(int i = 0; i < bits.length; i++)
{
if(bits[i] == spec)
return dataTableGetString(CITY_SPECS, i, "SPECIALIZATION");
}
return null;
}
//------------------------------------------------
// cityGetSpecCost
//------------------------------------------------
int cityGetSpecCost(int city_id)
{
int spec = cityGetSpec(city_id);
int[] bits = dataTableGetIntColumn(CITY_SPECS, "BIT");
for(int i = 0; i < bits.length; i++)
{
if(bits[i] == spec)
return dataTableGetInt(CITY_SPECS, i, "COST");
}
return 0;
}
//------------------------------------------------
// isCityZoned
//------------------------------------------------
boolean isCityZoned(int city_id)
{
obj_id city_hall = cityGetCityHall(city_id);
int flags = cityGetStructureType(city_id, city_hall);
return (0 != (flags & SF_REQUIRE_ZONE_RIGHTS));
}
//------------------------------------------------
// setCityZoned
//------------------------------------------------
void setCityZoned(int city_id, boolean zoned)
{
obj_id city_hall = cityGetCityHall(city_id);
int flags = cityGetStructureType(city_id, city_hall);
if(zoned)
flags |= SF_REQUIRE_ZONE_RIGHTS;
else
flags = flags & ~SF_REQUIRE_ZONE_RIGHTS;
setStructureType(city_id, city_hall, flags);
string city_name = cityGetName(city_id);
CustomerServiceLog("player_city", "Setting zoning requirement. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Zoning: " + zoned);
}
//------------------------------------------------------------------------------------------------
// UTILS
//------------------------------------------------------------------------------------------------
//------------------------------------------------
// checkCity
//------------------------------------------------
int checkCity(obj_id self, boolean notify)
{
// Check to see if we are in a city.
obj_id checkobj = self;
obj_id structure = getTopMostContainer(self);
if(structure != null)
checkobj = structure;
int city_id = getCityAtLocation(getLocation(checkobj), 0);
if(!cityExists(city_id))
{
city_id = getCityAtLocation(getLocation(getTopMostContainer(checkobj)), 0);
if(!cityExists(city_id))
{
if(notify)
sendSystemMessage(self, SID_NOT_IN_CITY);
return 0;
}
}
return city_id;
}
//------------------------------------------------
// checkMayorCity
//------------------------------------------------
int checkMayorCity(obj_id self, boolean notify)
{
int city_id = checkCity(self, notify);
if(city_id == 0)
return 0;
// Make sure we are mayor of this city.
obj_id mayor = cityGetLeader(city_id);
if(mayor != self)
return 0;
return city_id;
}
//------------------------------------------------
// isNormalStructure
//------------------------------------------------
boolean isNormalStructure(int city_id, obj_id structure)
{
int flags = cityGetStructureType(city_id, structure);
if(0 != (flags & SPECIAL_STRUCTURE))
return false;
return true;
}
//------------------------------------------------
// isPayStructure
//------------------------------------------------
boolean isPayStructure(int city_id, obj_id structure)
{
int flags = cityGetStructureType(city_id, structure);
if(0 == (flags & PAY_STRUCTURE))
return false;
return true;
}
//------------------------------------------------
// isMissionTerminal
//------------------------------------------------
boolean isMissionTerminal(int city_id, obj_id structure)
{
int flags = cityGetStructureType(city_id, structure);
if(0 != (flags & SF_MISSION_TERMINAL))
return true;
return false;
}
//------------------------------------------------
// isSkillTrainer
//------------------------------------------------
boolean isSkillTrainer(int city_id, obj_id structure)
{
int flags = cityGetStructureType(city_id, structure);
if(0 != (flags & SF_SKILL_TRAINER))
return true;
return false;
}
//------------------------------------------------
// isDecoration
//------------------------------------------------
boolean isDecoration(int city_id, obj_id structure)
{
int flags = cityGetStructureType(city_id, structure);
if(0 != (flags & SF_DECORATION))
return true;
return false;
}
//------------------------------------------------
// setStructureCityId
//------------------------------------------------
int setStructureCityId(obj_id structure, int city_id)
{
if(player_structure.isBuilding(structure))
setBuildingCityId(structure, city_id);
else
setObjVar(structure, "city_id", city_id); // Suppress linting - lint script incorrectly catches this
return city_id;
}
//------------------------------------------------
// getStructureCityId
//------------------------------------------------
int getStructureCityId(obj_id structure)
{
if(player_structure.isBuilding(structure))
return getBuildingCityId(structure);
else
return getIntObjVar(structure, "city_id");
}
//------------------------------------------------
// clearAbsenceFlags
//------------------------------------------------
void clearAbsenceFlags(obj_id citizen, int city_id)
{
string citname = cityGetCitizenName(city_id, citizen);
obj_id citall = cityGetCitizenAllegiance(city_id, citizen);
int flags = cityGetCitizenPermissions(city_id, citizen);
flags = flags & ~CP_ABSENT_WEEK_1;
flags = flags & ~CP_ABSENT_WEEK_2;
flags = flags & ~CP_ABSENT_WEEK_3;
flags = flags & ~CP_ABSENT_WEEK_4;
flags = flags & ~CP_ABSENT_WEEK_5;
citySetCitizenInfo(city_id, citizen, citname, citall, flags);
}
void doMayoralStructureTransfer(obj_id new_mayor, obj_id ousted_mayor, int city_id)
{
if(!isIdValid(new_mayor))
{
CustomerServiceLog("player_city_transfer", "New Mayor Structure Transfer Failed! New Mayor ID is not valid. City: (" + city_id + ") " + cityGetName(city_id) + ".");
return;
}
if(!cityExists(city_id))
{
CustomerServiceLog("player_city_transfer", "New Mayor Structure Transfer Failed! City does not exist: (" + city_id + ") " + cityGetName(city_id) + ". Mayor is (" + new_mayor + ") " + cityGetCitizenName(city_id, new_mayor));
return;
}
dictionary outparams = new dictionary();
outparams.put("mayor", new_mayor);
outparams.put("ousted_mayor", ousted_mayor);
outparams.put("newMayor", true); //needs to be 'true' if coming from an election vs. placing a structure.
obj_id[] structures = cityGetStructureIds(city_id);
if(structures == null || structures.length <= 0)
{
CustomerServiceLog("player_city_transfer", "New Mayor Structure Transfer Failed! (" + new_mayor + ") " + cityGetCitizenName(city_id, new_mayor) + " of City (" + city_id + ") " + cityGetName(city_id) + " array was null or empty.");
return;
}
/*
************************* City Hall *** Cloning Center ****************************
* The above structures can have noTrade items in them. this is causing transfers *
* to fail. Move these items to the Old Mayor. *
***********************************************************************************
*/
for(int i = 0; i < structures.length; i++)
{
if(city.isNormalStructure(city_id, structures[i]))
{
if(!messageTo(structures[i], "setNewMayor", outparams, 5.0f, true))
{
CustomerServiceLog("player_city_transfer", "City Civic Structure Transfer - MessageTo Failed: Structure(" + structures[i] + ") should be owned by Mayor(" + new_mayor + ") " + cityGetCitizenName(city_id, new_mayor) + ".");
}
}
if(city.isDecoration(city_id, structures[i]))
{
if(!messageTo(structures[i], "setNewMayor", outparams, 5.0f, true))
{
CustomerServiceLog("player_city_transfer", "City Decoration Transfer - MessageTo Failed: Structure(" + structures[i] + ") should be owned by Mayor(" + new_mayor + ") " + cityGetCitizenName(city_id, new_mayor) + ".");
}
}
}
}
void moveNoTradeItemsInStructureToOwner(obj_id building, obj_id ousted_mayor, int city_id)
{
obj_id buildingOwner = getOwner(building);
if((isIdValid(buildingOwner) && ousted_mayor == buildingOwner))
{
obj_id[] cellList = getContents(building);
if(cellList != null && cellList.length > 0)
{
for(int i = 0; i < cellList.length; i++)
{
if(getTemplateName(cellList[i]).equals(structure.TEMPLATE_CELL))
{
checkItemsForNoTradeTransfer(cellList[i], buildingOwner, city_id);
}
}
}
}
else
{
CustomerServiceLog("player_city_transfer", "Mayor Change: Attempted to move NoTrade Items to Ousted Mayor's Inventory but failed: Structure Owner(" + buildingOwner + ") " + cityGetCitizenName(city_id, buildingOwner) + " was not the same as the Ousted Mayor(" + ousted_mayor + ") " + cityGetCitizenName(city_id, ousted_mayor) + ".");
}
}
void checkItemsForNoTradeTransfer(obj_id container, obj_id player, int city_id)
{
if(!isIdValid(container))
{
CustomerServiceLog("player_city_transfer", "Mayoral NoTrade Item Transfer stopped - ContainerID was Invalid - " + container + ".");
return;
}
if(!isIdValid(player))
{
CustomerServiceLog("player_city_transfer", "Mayoral NoTrade Item Transfer stopped - PlayerID(Ousted Mayor) was Invalid - " + container + ".");
return;
}
obj_id[] cellContents = getContents(container);
if(cellContents != null && cellContents.length > 0)
{
for(int j = 0; j < cellContents.length; j++)
{
obj_id object = cellContents[j];
if(isIdValid(object))
{
boolean isValidPlayerOwnedObject = true;
obj_id objectOwner = getOwner(object);
if(player != objectOwner)
{
if(hasScript(object, "item.special.nomove"))
{
CustomerServiceLog("player_city_transfer", "Mayoral NoTrade Item Transfer - (" + object + ") " + getEncodedName(object) + " is NOT OWNED BY (" + player + ") " + cityGetCitizenName(city_id, player) + "(the ousted mayor) But was inside the City Hall/Cloning Center at the time of transfer of City: " + cityGetName(city_id) + ". Item is actually owned by (" + objectOwner + ") " + getEncodedName(objectOwner) + ".");
isValidPlayerOwnedObject = false;
}
}
if(!isObjectPersisted(object))
isValidPlayerOwnedObject = false;
if(isPlayer(object))
isValidPlayerOwnedObject = false;
if(isMob(object))
isValidPlayerOwnedObject = false;
if(hasCondition(object, CONDITION_VENDOR))
isValidPlayerOwnedObject = false;
if(isValidPlayerOwnedObject)
{
//Container - and is not NoTrade - Search through its contents.
if(getContainerType(object) != 0 && getGameObjectType(object) != GOT_misc_factory_crate && !hasScript(object, "item.special.nomove"))
{
checkItemsForNoTradeTransfer(object, player, city_id);
}
//Any Item that is NoTrade
if(hasScript(object, "item.special.nomove"))
{
CustomerServiceLog("player_city_transfer", "Mayoral NoTrade Item Transfer - NoTrade Item(" + object + ") " + getEncodedName(object) + " moved to ousted Mayor's(" + player + ") " + cityGetCitizenName(city_id, player) + " Inventory. The item was located in a CityHall or Cloning Center when the City: (" + cityGetName(city_id) + ")" + cityGetName(city_id) + " transferred.");
moveToOfflinePlayerInventoryAndUnload(object, player);
}
}
}
}
}
}
/*
Checks to see if the player has FULL zoning rights or is a Mayor/Militiaman.
Returns true if they can legally place a structure inside the City Limits, false otherwise.
*/
boolean hasZoningRights(obj_id player, int city_id)
{
if(!isIdValid(player) || city_id <= 0)
return false;
int cur_time = getGameTime();
//if you are Mayor or Militia - return true
if(cityGetLeader(city_id) == player || isMilitiaOfCity(player, city_id))
return true;
//if you have full zoning rights - check time
if(hasObjVar(player, "city.zoning_rights") && hasObjVar(player, "city.zoning_rights_time"))
{
int city_identification_objvar = getIntObjVar(player, "city.zoning_rights");
if(city_id != city_identification_objvar) //are you in the right city?
return false;
int rights_time = getIntObjVar(player, "city.zoning_rights_time");
if(cur_time - rights_time > (24*60*60)) //have your rights expired?
return false;
else
return true;
}
return false;
}
/*
Checks to see if the player has Storyteller zoning rights or is a Mayor/Militiaman.
Returns true if they can legally place a structure inside the City Limits, false otherwise.
*/
boolean hasStorytellerZoningRights(obj_id player, int city_id)
{
if(!isIdValid(player) || city_id <= 0)
return false;
//if you are Mayor or Militia - return true
if(cityGetLeader(city_id) == player || isMilitiaOfCity(player, city_id))
return true;
int cur_time = getGameTime();
//if you have full zoning rights - check time
if(hasObjVar(player, "city.zoning_rights") && hasObjVar(player, "city.zoning_rights_time"))
{
int city_identification_objvar = getIntObjVar(player, "city.zoning_rights");
if(city_id == city_identification_objvar)
{
int rights_time = getIntObjVar(player, "city.zoning_rights_time");
if(cur_time - rights_time <= (24*60*60))
return true;
}
}
//if you have storyteller zoning rights - check time
if(hasObjVar(player, "city.st_zoning_rights") && hasObjVar(player, "city.st_zoning_rights_time"))
{
int[] zoning_rights_array = getIntArrayObjVar(player, "city.st_zoning_rights");
int[] zoning_times_array = getIntArrayObjVar(player, "city.st_zoning_rights_time");
//Let's go through all Cities he/she has storyteller zoning for
for(int i = 0; i < zoning_rights_array.length; i++)
{
if(zoning_rights_array[i] != city_id)
continue;
//city_id match
if(cur_time - zoning_times_array[i] > (24*60*60))
break;
else
return true;
}
}
return false;
}
//------------------------------------------------
// Citizen Protected from Packup
//
// Mayors can protect a Citizen's house from demolition
//------------------------------------------------
boolean hasMayorProtectionFlag(obj_id player, int city_id)
{
if(!cityExists(city_id))
return false;
if(!isIdValid(player))
return false;
int flags = cityGetCitizenPermissions(city_id, player);
if(0 != (flags & CP_INACTIVE_PROTECTED))
return true;
return false;
}
//------------------------------------------------
// Safe House Count = 20% of the required population
//------------------------------------------------
int getMaxSafeHouseCount(int city_id)
{
int currentRank = getCityRank(city_id);
int safeCount = 0;
switch(currentRank)
{
case 1:
safeCount = 1;
break;
case 2:
safeCount = 2;
break;
case 3:
safeCount = 3;
break;
case 4:
safeCount = 6;
break;
case 5:
safeCount = 8;
break;
default:
break;
}
return safeCount;
}
//------------------------------------------------
// Gets the current number of Safe Houses the Mayor is using.
//------------------------------------------------
int getCurrentSafeHouseCount(int city_id)
{
//go through the citizen list and see who is protected.
obj_id[] citizens = cityGetCitizenIds(city_id);
int tracker = 0;
if(citizens == null || citizens.length <= 0)
{
return 0;
}
for(int i = 0; i < citizens.length; i++)
{
if(!hasMayorProtectionFlag(citizens[i], city_id))
continue;
else
tracker++;
}
return tracker;
}
//------------------------------------------------
// Add a Safe Citizen
//------------------------------------------------
void addSafeHouseCitizen(int city_id, obj_id citizen)
{
obj_id mayor = cityGetLeader(city_id);
int flags = cityGetCitizenPermissions(city_id, citizen);
flags = flags | CP_INACTIVE_PROTECTED;
obj_id cit_all = cityGetCitizenAllegiance(city_id, citizen);
citySetCitizenInfo(city_id, citizen, cityGetCitizenName(city_id, citizen), cit_all, flags);
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Added Safe House. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Citizen: " + citizen + " is now protected from City Packup Rules.");
}
//------------------------------------------------
// Remove a Safe Citizen
//------------------------------------------------
void removeSafeHouseCitizen(int city_id, obj_id citizen)
{
obj_id mayor = cityGetLeader(city_id);
int flags = cityGetCitizenPermissions(city_id, citizen);
flags = flags & ~CP_INACTIVE_PROTECTED;
obj_id cit_all = cityGetCitizenAllegiance(city_id, citizen);
citySetCitizenInfo(city_id, citizen, cityGetCitizenName(city_id, citizen), cit_all, flags);
string city_name = cityGetName(city_id);
obj_id city_hall = cityGetCityHall(city_id);
CustomerServiceLog("player_city", "Removed Safe House. City: " + city_name + " (" + city_id + "/" + city_hall + ")" + " Citizen: " + citizen + " is no longer protected from City Packup Rules");
}
//returns the list of Safe House Citizens in a given City.
obj_id[] getCitySafeHouseCitizenList(int city_id)
{
resizeable obj_id[] safeHouseCitizens = new obj_id[0];
//utils.addElement(loadedStructures, structures[i]);
if(!cityExists(city_id))
{
LOG("sissynoid", "Attempting to remove Safe House Citizen(s) - but City does not exist: City ID: " + city_id);
CustomerServiceLog("player_city", "Attempting to remove Safe House Citizen(s) - but City does not exist: City ID: " + city_id);
return null;
}
obj_id[] citizens = cityGetCitizenIds(city_id);
if(citizens == null || citizens.length <= 0)
{
LOG("sissynoid", "Attempting to remove Safe House Citizen(s) - but City does not Citizens(citizen array was null): CityID:" + city_id);
CustomerServiceLog("player_city", "Attempting to remove Safe House Citizen(s) - but City does not Citizens(citizen array was null): CityID:" + city_id);
return null;
}
for(int i = 0; i < citizens.length; i++)
{
if(!hasMayorProtectionFlag(citizens[i], city_id))
continue;
else
utils.addElement(safeHouseCitizens, citizens[i]);
}
//convert to static array
obj_id[] returnArray = utils.toStaticObjIdArray(safeHouseCitizens);
return returnArray;
}