/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//Filename : OTOWN.H
//Description : Header file of Object Town
#ifndef __OTOWN_H
#define __OTOWN_H
#ifndef __ODYNARRB_H
#include
#endif
#ifndef __OSKILL_H
#include
#endif
#ifndef __OFIRMID_H
#include
#endif
#ifndef __ORAWRES_H
#include
#endif
#ifndef __OTOWNRES_H
#include
#endif
//------- define constant --------//
#define MAX_TOWN_GROWTH_POPULATION 60 // grow up to 60 persons in a town
#define MAX_TOWN_POPULATION 60 // max number of unitw in a town
//-------- Define constant -----------//
#define STD_TOWN_LOC_WIDTH 4
#define STD_TOWN_LOC_HEIGHT 4
//--------- Define training cost and level --------//
#define TRAIN_SKILL_COST 30
#define TRAIN_SKILL_LEVEL 20
#define TOTAL_TRAIN_DAYS 5 // No. of days needed for training an unit
#define MIN_RECRUIT_LOYALTY 30 // only when loyalty > this, the unit can be recruited
#define MIN_NATION_DEFEND_LOYALTY 50 // if the loyalty of the town people > this, they will defense against the attack
#define MIN_INDEPENDENT_DEFEND_LOYALTY 30
#define SURRENDER_LOYALTY 29 // when the loyalty of the town is <= this, and being attacked by a nation, the town will surrender
#define REBEL_LOYALTY 29 // if loyalty <= REBEL_LOYALTY, the unit may rebel
#define INDEPENDENT_LINK_RESISTANCE 50 // only if the resistance of an independent town is lower than this, the town will enable its link with a foreign firm
#define TAX_PER_PERSON 5 // amount of tax can be collected from each person
#define COLLECT_TAX_LOYALTY_DECREASE 10 // Reduce 10 loyalty points per tax collection
#define TOWN_REWARD_PER_PERSON 10
#define TOWN_REWARD_LOYALTY_INCREASE 10
#define IND_TOWN_GRANT_PER_PERSON 30 // independent town granting cost per person
#define IND_TOWN_GRANT_RESISTANCE_DECREASE 10 // resistance decrease per grant
#define RECEIVED_HIT_PER_KILL (200/ATTACK_SLOW_DOWN) // no. of received hits will result in one death of town people
#define MAX_TRAIN_QUEUE 10
//-------- Define class Town ----------//
class Unit;
#pragma pack(1)
class Town
{
public:
enum { TOWN_NAME_LEN=20 };
short town_recno;
short town_name_id;
char* town_name() { return town_res.get_name(town_name_id); }
short nation_recno;
short rebel_recno; // whether this town is controlled by a rebel
char race_id;
int setup_date; // the setup date of this town
char ai_town;
char ai_link_checked; // AI check firm and town locatin by links, disable checking by setting this parameter to 1
char independ_town_nation_relation; // each bit n is high representing this independent town will attack nation n.
char has_linked_own_camp; // whether the town has linked military camps of the same nation
char has_linked_enemy_camp; // whether the town has linked military camps of the same nation
char is_base_town; // whether this town is base town or not
short loc_x1, loc_y1, loc_x2, loc_y2;
short abs_x1, abs_y1, abs_x2, abs_y2;
short loc_width() { return loc_x2-loc_x1+1; }
short loc_height() { return loc_y2-loc_y1+1; }
short center_x;
short center_y;
BYTE region_id;
short layout_id; // town layout id.
short first_slot_id; // the first slot id. of the layout
short slot_object_id_array[MAX_TOWN_LAYOUT_SLOT]; // the race id. of each slot building
//---------- game vars ----------//
short population;
short jobless_population;
short worker_population() { return population-jobless_population; }
short max_race_pop_array[MAX_RACE]; // the max population the current town layout supports
short race_pop_array[MAX_RACE]; // population of each race
unsigned char race_pop_growth_array[MAX_RACE]; // population growth, when it reaches 100, there will be one more person in the town
short jobless_race_pop_array[MAX_RACE];
int recruitable_race_pop(int raceId, int recruitSpy);
float race_loyalty_array[MAX_RACE];
char race_target_loyalty_array[MAX_RACE];
short race_spy_count_array[MAX_RACE]; // no. of spies in each race
float race_resistance_array[MAX_RACE][MAX_NATION];
char race_target_resistance_array[MAX_RACE][MAX_NATION];
int race_harmony(int raceId);
int majority_race(); // the race that has the majority of the population
int average_loyalty();
int average_target_loyalty();
int average_resistance(int nationRecno);
int average_target_resistance(int nationRecno);
short town_defender_count; // no. of units currently defending this town
int last_being_attacked_date;
float received_hit_count; // no. of received hit by attackers, when this > RECEIVED_HIT_PER_KILL, a town people will be killed
char train_queue_skill_array[MAX_TRAIN_QUEUE]; // it stores the skill id.
char train_queue_race_array[MAX_TRAIN_QUEUE]; // it stores the race id.
char train_queue_count;
short train_unit_recno; // race id. of the unit the town is currently training, 0-if currently not training any
int train_unit_action_id; // id. of the action to be assigned to this unit when it is finished training.
DWORD start_train_frame_no;
short defend_target_recno; // used in defend mode, store recno of latest target atttacking this town
//-------- other vars ----------//
int accumulated_collect_tax_penalty;
int accumulated_reward_penalty;
int accumulated_recruit_penalty;
int accumulated_enemy_grant_penalty;
int last_rebel_date;
short independent_unit_join_nation_min_rating;
short quality_of_life;
void update_quality_of_life();
//------- auto policy -------------//
short auto_collect_tax_loyalty; // auto collect tax if the loyalty reaches this level
short auto_grant_loyalty; // auto grant if the loyalty drop below this level
//----------- AI vars ------------//
char town_combat_level; // combat level of the people in this town
char has_product_supply[MAX_PRODUCT]; // whether this town has the supply of these products
char no_neighbor_space; // 1 if there is no space to build firms/towns next to this town
//------ inter-relationship -------//
short linked_firm_count;
short linked_town_count;
short linked_firm_array[MAX_LINKED_FIRM_TOWN];
short linked_town_array[MAX_LINKED_TOWN_TOWN];
char linked_firm_enable_array[MAX_LINKED_FIRM_TOWN];
char linked_town_enable_array[MAX_LINKED_TOWN_TOWN];
int closest_own_camp();
//------ static class member var ------//
static short if_town_recno;
public:
Town();
void init(int,int,int,int);
void deinit();
void next_day();
void draw(int displayLayer=1);
void process_ai();
void disp_info(int refreshFlag);
void detect_info();
int browse_selected_race_id();
void assign_unit(int unitRecno);
int recruit(int withTraining, int raceId, char remoteAction);
int recruit_dec_loyalty(int raceId, int decNow=1);
void cancel_train_unit();
int form_new_nation();
int can_recruit(int raceId);
int can_train(int raceId);
int can_migrate(int destTownRecno, int migrateNow=0, int raceId=0); // if not called by Town::mirgate, don't set migrateNow to TRUE
void move_pop(Town* destTown, int raceId, int hasJob);
int pick_random_race(int pickNonRecruitableAlso, int pickSpyFlag);
int camp_influence(int unitRecno);
void setup_link();
void release_link();
void release_firm_link(int);
void release_town_link(int);
int linked_active_camp_count();
int can_toggle_firm_link(int firmRecno);
void update_camp_link();
void init_pop(int raceId, int addPop, int loyalty, int hasJob=0, int firstInit=0);
void inc_pop(int raceId, int unitHasJob, int unitLoyalty);
void inc_pop_overcrowded(int raceId, int unitHasJob, int unitLoyalty);
void dec_pop(int raceId, int unitHasJob);
void draw_selected();
int draw_detect_link_line(int);
int is_in_zoom_win();
int has_linked_camp(int nationRecno, int needOverseer);
void auto_set_layout();
void set_nation(int nationRecno);
void surrender(int toNationRecno);
void set_hostile_nation(int nationRecno);
void reset_hostile_nation(int nationRecno);
int is_hostile_nation(int nationRecno);
int create_rebel_unit(int raceId, int isLeader);
int mobilize_town_people(int raceId, int decPop, int mobilizeSpy);
int mobilize_defender(int attackerNationRecno);
int migrate_to(int destTownRecno, char remoteAction, int raceId=0);
void collect_yearly_tax();
void collect_tax(char remoteAction);
void reward(char remoteAction);
void distribute_demand();
void being_attacked(int attackerUnitRecno, float attackDamage);
void clear_defense_mode();
void reduce_defender_count();
void kill_town_people(int raceId, int attackerUnitRecno=0);
int can_grant_to_non_own_town(int grantNationRecno);
int grant_to_non_own_town(int grantNationRecno, int remoteAction);
void get_most_populated_race(int& mostRaceId1, int& mostRaceId2);
void update_target_loyalty();
void update_target_resistance();
void update_loyalty();
void update_resistance();
void update_product_supply();
void change_loyalty(int raceId, float loyaltyChange);
void change_resistance(int raceId, int nationRecno, float loyaltyChange);
void toggle_firm_link(int linkId, int toggleFlag, char remoteAction, int setBoth=0);
void toggle_town_link(int linkId, int toggleFlag, char remoteAction, int setBoth=0);
void auto_defense(short targetRecno);
int has_player_spy();
void verify_slot_object_id_array();
void set_auto_collect_tax_loyalty(int loyaltyLevel);
void set_auto_grant_loyalty(int loyaltyLevel);
void disp_auto_loyalty();
void add_queue(char skillId, char raceId);
void remove_queue(char skillId);
int write_file(File*);
int read_file(File*);
//-------- ai functions ---------//
void think_collect_tax();
void think_reward();
int think_build_firm(int firmId, int maxFirm);
int think_build_market();
int think_build_camp();
int think_build_research();
int think_build_war_factory();
int think_build_base();
int think_build_inn();
int think_ai_migrate();
int think_ai_migrate_to_town();
void think_defense();
int think_split_town();
void think_move_between_town();
int think_attack_nearby_enemy();
int think_attack_linked_enemy();
void think_capture_linked_firm();
int think_capture_enemy_town();
int think_scout();
void update_base_town_status();
int new_base_town_status();
int think_counter_spy();
int needed_anti_spy_level();
int think_spying_town();
int think_spying_town_assign_to(int raceId);
int should_ai_migrate();
int detect_enemy(int);
int protection_needed(); // an index from 0 to 100 indicating the military protection needed for this town
int protection_available();
int ai_build_neighbor_firm(int firmId, int firmRaceId=0);
int ai_settle_new(int raceId);
//-------- independent town ai functions ---------//
void think_independent_town();
void think_independent_set_link();
int think_independent_form_new_nation();
int think_independent_unit_join_nation();
int independent_unit_join_nation(int raceId, int toNationRecno);
//--------- function for cheat key ----------//
int get_selected_race();
//-------------- multiplayer checking codes ---------------//
UCHAR crc8();
void clear_ptr();
//-------------------------------//
private:
void set_world_matrix();
void restore_world_matrix();
void establish_contact_with_player();
void process_food();
void process_auto();
void process_train();
void finish_train(Unit*);
void population_grow();
void process_queue();
void think_migrate();
int think_migrate_one(Town* targetTown, int raceId, int townDistance);
void migrate(int raceId, int destTownZoneRecno, int newLoyalty);
// int can_migrate(int destTownRecno, int migrateNow=0, int raceId=0);
int unjob_town_people(int raceId, int unjobOverseer, int killOverseer=0);
// void kill_town_people(int raceId);
int think_layout_id();
void draw_flag(int,int);
void draw_farm(int,int,int);
void disp_basic_info(int refreshFlag);
void disp_train_info(int refreshFlag);
void disp_main_menu(int refreshFlag);
void detect_main_menu();
void disp_debug_resistance(int refreshFlag);
void disp_train_menu(int refreshFlag);
void disp_train_button(int y, int skillId, int buttonUp);
void disp_queue_button(int y, int skillId, int buttonUp);
void detect_train_menu();
void disp_auto_menu(int modeCollectTax);
void detect_auto_menu(int modeCollectTax);
void disp_spy_menu(int refreshFlag);
void detect_spy_menu();
void daily_update_loyalty();
void calc_loyalty();
void think_rebel();
int think_surrender();
};
#pragma pack()
//-------- Begin of class TownArray ------------//
class TownArray : public DynArrayB
{
public:
int selected_recno; // the firm current being selected
int race_wander_pop_array[MAX_RACE]; // no. of wandering people of each race. They are people for setting up independent towns later
public:
TownArray();
~TownArray();
void init();
void deinit();
int add_town(int nationRecno, int raceId, int xLoc, int yLoc);
void del_town(int townRecno);
Town* create_town();
void draw();
void draw_dot();
void draw_profile();
void process();
int independent_town_resistance();
void think_new_independent_town();
int think_town_loc(int maxTries, int& xLoc, int& yLoc);
int find_nearest_town(int xLoc, int yLoc, int nationRecno=0);
int settle(int unitRecno, int xLoc, int yLoc);
void distribute_demand();
void stop_attack_nation(short nationRecno);
int write_file(File*);
int read_file(File*);
int is_deleted(int recNo);
#ifdef DEBUG
Town* operator[](int recNo);
#else
Town* operator[](int recNo) { return (Town*) get_ptr(recNo); }
#endif
};
extern TownArray town_array;
//---------------------------------------------------//
#endif