mirror of
https://bitbucket.org/seefoe/dsrc.git
synced 2026-07-31 01:15:55 -04:00
2683 lines
77 KiB
Plaintext
2683 lines
77 KiB
Plaintext
/**
|
|
* Copyright (c) ©2003 Sony Online Entertainment Inc.
|
|
* All Rights Reserved
|
|
*
|
|
* Title: city library
|
|
* @author $Author: Brandon Reinhart$
|
|
* @version $Revision: #1 $
|
|
*/
|
|
|
|
//------------------------------------------------
|
|
// 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 = new_loc;
|
|
|
|
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;
|
|
}
|