/* * 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 : OU_GOD.CPP //Description: God Unit #include #include #include #include #include #include #include #include #include #include #include //--------- Define static vars ----------// static Button3D button_cast, button_cast2; //--------- Begin of function UnitGod::init_derived --------// void UnitGod::init_derived() { // ##### patch begin Gilbert 22/1 ######// cast_power_type = 0; // ##### end begin Gilbert 22/1 ######// if(unit_id==UNIT_PERSIAN_HEALER || unit_id==UNIT_VIKING_GOD || unit_id==UNIT_KUKULCAN || unit_id==UNIT_JAPANESE_GOD) can_attack_flag = 0; // unable to attack #ifdef AMPLUS if(unit_id==UNIT_EGYPTIAN_GOD || unit_id==UNIT_INDIAN_GOD || unit_id==UNIT_ZULU_GOD) can_attack_flag = 0; // unable to attack #endif } //-------- End of function UnitGod::init_derived -------// //------- Begin of function UnitGod::pre_process -------// // void UnitGod::pre_process() { Unit::pre_process(); if( game.game_mode == GAME_TEST ) return; //---- set force_move_flag to 1 if the god does not have the ability to attack ----// if( god_id != GOD_CHINESE && god_id != GOD_NORMAN ) // only Chinese and Norman dragon can attack force_move_flag = 1; //-*********** simulate aat ************-// #ifdef DEBUG if(debug_sim_game_type) return; #endif //-*********** simulate aat ************-// //--- if the seat of power supporting this unit is destroyed, this unit dies ---// if( firm_array.is_deleted(base_firm_recno) ) { hit_points=(float)0; set_die(); return; } //---- this unit consume pray points as it exists ----// FirmBase* firmBase = (FirmBase*) firm_array[base_firm_recno]; err_when( firmBase->firm_id != FIRM_BASE ); firmBase->pray_points -= (float) god_res[god_id]->exist_pray_points / 200; if( firmBase->pray_points < 0 ) firmBase->pray_points = (float) 0; //--------- update hit points --------// hit_points = (short) firmBase->pray_points; if( hit_points == 0 ) set_die(); } //-------- End of function UnitGod::pre_process -------// //--------- Begin of function UnitGod::process_attack --------// int UnitGod::process_attack() { if( !Sprite::process_attack() ) // return 1 if the unit just finished its current attack return 0; if( game.game_mode == GAME_TEST ) return 1; //-*********** simulate aat ************-// #ifdef DEBUG if(debug_sim_game_type) return 1; #endif //-*********** simulate aat ************-// consume_power_pray_points(); return 1; } //---------- End of function UnitGod::process_attack ----------// //--------- Begin of function UnitGod::disp_info ---------// // void UnitGod::disp_info(int refreshFlag) { disp_basic_info(INFO_Y1, refreshFlag); disp_unit_profile( INFO_Y1+54, refreshFlag ); if( !is_own() ) return; if( game.game_mode == GAME_TEST ) return; if( god_res[god_id]->can_cast_power ) { //-------- get the button name --------// char* buttonName; switch(god_id) { case GOD_PERSIAN: buttonName = "GODHEAL"; break; case GOD_JAPANESE: buttonName = "GODMIND"; break; case GOD_MAYA: buttonName = "GODINCCL"; break; case GOD_VIKING: buttonName = "GODRAIN"; break; #ifdef AMPLUS case GOD_EGYPTIAN: buttonName = "GODEGYPT"; break; case GOD_INDIAN: buttonName = "GODMUGL"; break; case GOD_ZULU: buttonName = "GODZULU"; break; #endif default: err_here(); } //----------- create the cast button -----------// button_cast.paint(INFO_X1, INFO_Y1+101, 'A', buttonName ); if( hit_points >= god_res[god_id]->power_pray_points ) button_cast.enable(); else button_cast.disable(); //------ The viking gods have two types of power ------// if( god_id == GOD_VIKING ) { button_cast2.paint(INFO_X1+BUTTON_ACTION_WIDTH, INFO_Y1+101, 'A', "GODTORNA" ); if( hit_points >= god_res[god_id]->power_pray_points ) button_cast2.enable(); else button_cast2.disable(); } } } //---------- End of function UnitGod::disp_info ----------// //--------- Begin of function UnitGod::detect_info ---------// // void UnitGod::detect_info() { if( detect_basic_info() ) return; if( detect_unit_profile() ) return; if( !is_own() ) return; if( game.game_mode == GAME_TEST ) return; if( god_res[god_id]->can_cast_power ) { // ###### begin Gilbert 14/10 ######// int rc=0; char castPowerType = 0; if( button_cast.detect() ) { // cast_power_type = 1; castPowerType = 1; rc = 1; } if( button_cast2.detect() ) { castPowerType = 2; //cast_power_type = 2; //cast_origin_x = cur_x_loc(); //cast_origin_y = cur_y_loc(); rc = 1; } //----------------------------------------// if( rc && castPowerType) { if( god_id == GOD_VIKING && castPowerType == 1 ) // summon rain, summon immediately, no need to select target go_cast_power(next_x_loc(), next_y_loc(), castPowerType, COMMAND_PLAYER); else power.issue_command(COMMAND_GOD_CAST_POWER, sprite_recno, castPowerType); } // ###### end Gilbert 14/10 ######// } } //---------- End of function UnitGod::detect_info ----------// //--------- Begin of function UnitGod::cast_power ---------// // // castXLoc, castYLoc - the location which the power should // be casted on. // void UnitGod::cast_power(int xLoc, int yLoc) { err_when( !god_res[god_id]->can_cast_power ); //------- consumer pray points --------// // consume_power_pray_points(); // let process_attack to consume //---- viking god does not need a range for casting power ----// if( god_id == GOD_VIKING ) { if( cast_power_type == 1 ) viking_summon_rain(); else viking_summon_tornado(); return; } //------ cast power on the selected area ------// GodInfo* godInfo = god_res[god_id]; int xLoc1 = xLoc - godInfo->cast_power_range + 1; int yLoc1 = yLoc - godInfo->cast_power_range + 1; int xLoc2 = xLoc + godInfo->cast_power_range - 1; int yLoc2 = yLoc + godInfo->cast_power_range - 1; int t; int centerY = (yLoc1+yLoc2) / 2; Location* locPtr; for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { t=abs(yLoc-centerY)/2; locPtr = world.get_loc(xLoc1+t, yLoc); for( xLoc=xLoc1+t ; xLoc<=xLoc2-t ; xLoc++, locPtr++ ) { if( xLoc>=0 && xLoc=0 && yLoc 0 ) yLoc--; if( dir >= 1 && dir <= 3 ) if( xLoc < MAX_WORLD_X_LOC-1 ) xLoc++; if( dir >= 3 && dir <= 5 ) if( yLoc < MAX_WORLD_Y_LOC-1) yLoc++; if( dir >= 5 && dir <= 7 ) if( xLoc > 0 ) xLoc--; tornado_array.add_tornado( xLoc, yLoc, 600 ); magic_weather.cast_wind(10, 1, dir * 45 ); // 10 days } //---------- End of function UnitGod::viking_summon_tornado ----------// //--------- Begin of function UnitGod::cast_on_loc ---------// // void UnitGod::cast_on_loc(int castXLoc, int castYLoc) { Location* locPtr = world.get_loc( castXLoc, castYLoc ); //--- if there is any unit on the location ---// if( locPtr->has_unit(UNIT_LAND) ) { cast_on_unit( locPtr->unit_recno(UNIT_LAND), 1 ); } else if( locPtr->has_unit(UNIT_SEA) ) { Unit* unitPtr = unit_array[ locPtr->unit_recno(UNIT_SEA) ]; //-- only heal human units belonging to our nation in ships --// if( unitPtr->nation_recno == nation_recno && unit_res[unitPtr->unit_id]->unit_class == UNIT_CLASS_SHIP ) { UnitMarine* unitMarine = (UnitMarine*) unitPtr; for( int i=0 ; iunit_count ; i++ ) { int divider = 4; // the size of a ship is 4 locations (2x2) cast_on_unit( unitMarine->unit_recno_array[i], divider ); // the effects are weaken on ship units, only 50% of the original effects } } } //--------- on firms ---------// else if( locPtr->is_firm() ) { Firm* firmPtr = firm_array[ locPtr->firm_recno() ]; int divider = (firmPtr->loc_x2-firmPtr->loc_x1+1) * (firmPtr->loc_y2-firmPtr->loc_y1+1); #ifdef AMPLUS if( god_id == GOD_ZULU ) divider = 1; // range of zulu god is 1, no need to divide #endif if( firmPtr->overseer_recno ) { cast_on_unit( firmPtr->overseer_recno, divider ); } if( firmPtr->worker_array && firm_res[firmPtr->firm_id]->live_in_town==0 ) { Worker* workerPtr = firmPtr->worker_array; for( int i=0 ; iworker_count ; i++, workerPtr++ ) { cast_on_worker(workerPtr, firmPtr->nation_recno, divider); } } } //--------- on towns ----------// else if( locPtr->is_town() ) { Town* townPtr = town_array[ locPtr->town_recno() ]; if( god_id == GOD_JAPANESE && townPtr->nation_recno != nation_recno) { int divider = STD_TOWN_LOC_WIDTH * STD_TOWN_LOC_HEIGHT; for( int i=0 ; irace_pop_array[i]==0 ) continue; float changePoints = (float)7 + m.random(8); // decrease 7 to 15 loyalty points instantly if( townPtr->nation_recno ) townPtr->change_loyalty(i+1, -changePoints/divider); else townPtr->change_resistance(i+1, nation_recno, -changePoints/divider); } } #ifdef AMPLUS else if( god_id == GOD_EGYPTIAN && townPtr->nation_recno == nation_recno) { int headCount; int raceId; for( headCount = 5; headCount > 0 && townPtr->population < MAX_TOWN_GROWTH_POPULATION && (raceId = townPtr->pick_random_race(1,1)); --headCount ) { townPtr->inc_pop(raceId, 0, (int)townPtr->race_loyalty_array[raceId-1]); } } #endif } } //---------- End of function UnitGod::cast_on_loc ----------// //--------- Begin of function UnitGod::cast_on_unit ---------// // // unitRecno - recno of the unit to cast on // divider - divide the amount of effects by this number // void UnitGod::cast_on_unit(int unitRecno, int divider) { switch(god_id) { case GOD_PERSIAN: persian_cast_power( unitRecno, divider ); break; case GOD_JAPANESE: japanese_cast_power( unitRecno, divider ); break; case GOD_MAYA: maya_cast_power( unitRecno, divider ); break; #ifdef AMPLUS case GOD_EGYPTIAN: egyptian_cast_power( unitRecno, divider); break; case GOD_INDIAN: indian_cast_power( unitRecno, divider); break; case GOD_ZULU: zulu_cast_power( unitRecno, divider); break; #endif default: err_here(); } } //---------- End of function UnitGod::cast_on_unit ----------// //--------- Begin of function UnitGod::cast_on_worker ---------// // // workerPtr - pointer to the worker to be affected by the effect. // void UnitGod::cast_on_worker(Worker* workerPtr, int nationRecno, int divider) { switch(god_id) { case GOD_PERSIAN: persian_cast_power( workerPtr, nationRecno, divider ); break; case GOD_JAPANESE: japanese_cast_power( workerPtr, nationRecno, divider ); break; case GOD_MAYA: maya_cast_power( workerPtr, nationRecno, divider ); break; #ifdef AMPLUS case GOD_EGYPTIAN: egyptian_cast_power(workerPtr, nationRecno, divider); break; case GOD_INDIAN: indian_cast_power(workerPtr, nationRecno, divider); break; case GOD_ZULU: zulu_cast_power(workerPtr, nationRecno, divider); break; #endif default: err_here(); } } //---------- End of function UnitGod::cast_on_worker ----------// //--------- Begin of function UnitGod::persian_cast_power ---------// // void UnitGod::persian_cast_power(int unitRecno, int divider) { Unit* unitPtr = unit_array[unitRecno]; //-- only heal human units belonging to our nation --// if( unitPtr->nation_recno == nation_recno && unitPtr->race_id > 0 ) { float changePoints = (float) unitPtr->max_hit_points / (6+m.random(4)); // divided by (6 to 9) changePoints = max( changePoints, 10 ); unitPtr->change_hit_points( changePoints/divider ); } } //---------- End of function UnitGod::persian_cast_power ----------// //--------- Begin of function UnitGod::japanese_cast_power ---------// // void UnitGod::japanese_cast_power(int unitRecno, int divider) { Unit* unitPtr = unit_array[unitRecno]; //-- only cast on enemy units -----// if( unitPtr->nation_recno != nation_recno && unitPtr->race_id > 0 ) { int changePoints = 7 + m.random(8); // decrease 7 to 15 loyalty points instantly unitPtr->change_loyalty( -max(1, changePoints/divider) ); } } //---------- End of function UnitGod::japanese_cast_power ----------// //--------- Begin of function UnitGod::maya_cast_power ---------// // void UnitGod::maya_cast_power(int unitRecno, int divider) { Unit* unitPtr = unit_array[unitRecno]; //-- only cast on mayan units belonging to our nation --// if( unitPtr->nation_recno == nation_recno && unitPtr->race_id == RACE_MAYA ) { int changePoints = 15 + m.random(10); // add 15 to 25 points to its combat level instantly int newCombatLevel = unitPtr->skill.combat_level + changePoints/divider; if( newCombatLevel > 100 ) newCombatLevel = 100; float oldHitPoints = unitPtr->hit_points; unitPtr->set_combat_level(newCombatLevel); unitPtr->hit_points = oldHitPoints; // keep the hit points unchanged. } } //---------- End of function UnitGod::maya_cast_power ----------// //--------- Begin of function UnitGod::persian_cast_power ---------// // void UnitGod::persian_cast_power(Worker* workerPtr, int nationRecno, int divider) { //-- only heal human units belonging to our nation --// if( nationRecno == nation_recno && workerPtr->race_id > 0 ) { int changePoints = workerPtr->max_hit_points() / (4+m.random(4)); // divided by (4 to 7) changePoints = max( changePoints, 10 ); workerPtr->change_hit_points( max(1, changePoints/divider) ); } } //---------- End of function UnitGod::persian_cast_power ----------// //--------- Begin of function UnitGod::japanese_cast_power ---------// // void UnitGod::japanese_cast_power(Worker* workerPtr, int nationRecno, int divider) { //-- only cast on enemy units -----// if( nationRecno != nation_recno && workerPtr->race_id > 0 ) { int changePoints = 7 + m.random(8); // decrease 7 to 15 loyalty points instantly workerPtr->change_loyalty( -max(1, changePoints/divider) ); } } //---------- End of function UnitGod::japanese_cast_power ----------// //--------- Begin of function UnitGod::maya_cast_power ---------// // void UnitGod::maya_cast_power(Worker* workerPtr, int nationRecno, int divider) { //-- only cast on mayan units belonging to our nation --// if( nationRecno == nation_recno && workerPtr->race_id == RACE_MAYA ) { int changePoints = 15 + m.random(10); // add 15 to 25 points to its combat level instantly int newCombatLevel = workerPtr->combat_level + max(1, changePoints/divider); if( newCombatLevel > 100 ) newCombatLevel = 100; workerPtr->combat_level = newCombatLevel; } } //---------- End of function UnitGod::maya_cast_power ----------// //--------- Begin of function UnitGod::consume_power_pray_points ---------// // void UnitGod::consume_power_pray_points() { FirmBase* firmBase = (FirmBase*) firm_array[base_firm_recno]; err_when( firmBase->firm_id != FIRM_BASE ); firmBase->pray_points -= god_res[god_id]->power_pray_points; if( firmBase->pray_points < 0 ) firmBase->pray_points = (float) 0; hit_points = (short) firmBase->pray_points; } //---------- End of function UnitGod::consume_power_pray_points ----------// #ifdef AMPLUS //--------- Begin of function UnitGod::egyptian_cast_power ---------// // void UnitGod::egyptian_cast_power(int unitRecno, int divider) { // no effect } //---------- End of function UnitGod::egyptian_cast_power ----------// //--------- Begin of function UnitGod::indian_cast_power ---------// // void UnitGod::indian_cast_power(int unitRecno, int divider) { Unit* unitPtr = unit_array[unitRecno]; if( unitPtr->is_visible() && nation_array.should_attack(nation_recno, unitPtr->nation_recno) ) { unitPtr->change_loyalty(-30 + m.random(11)); } } //---------- End of function UnitGod::indian_cast_power ----------// //--------- Begin of function UnitGod::zulu_cast_power ---------// // void UnitGod::zulu_cast_power(int unitRecno, int divider) { // no effect Unit* unitPtr = unit_array[unitRecno]; if( nation_recno == unitPtr->nation_recno && unitPtr->race_id == RACE_ZULU && unitPtr->rank_id != RANK_SOLDIER) { int changePoints = 30; // add 15 twice to avoid 130 becomes -126 if( divider > 2 ) { unitPtr->skill.skill_level += changePoints/divider; if( unitPtr->skill.skill_level > 100 ) unitPtr->skill.skill_level = 100; } else { for(int t = 2; t > 0; --t ) { unitPtr->skill.skill_level += changePoints/2/divider; if( unitPtr->skill.skill_level > 100 ) unitPtr->skill.skill_level = 100; } } } } //---------- End of function UnitGod::zulu_cast_power ----------// //--------- Begin of function UnitGod::egyptian_cast_power ---------// // void UnitGod::egyptian_cast_power(Worker *workerPtr, int nationRecno, int divider) { // no effect } //---------- End of function UnitGod::egyptian_cast_power ----------// //--------- Begin of function UnitGod::indian_cast_power ---------// // void UnitGod::indian_cast_power(Worker *workerPtr, int nationRecno, int divider) { // no effect } //---------- End of function UnitGod::indian_cast_power ----------// //--------- Begin of function UnitGod::zulu_cast_power ---------// // void UnitGod::zulu_cast_power(Worker *workerPtr, int nationRecno, int divider) { // no effect } //---------- End of function UnitGod::zulu_cast_power ----------// #endif