123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OUNITAT.CPP
- //Description : Object Unit attack supporting functions
- //Owner : Alex
- #include <ALL.h>
- #include <ONEWS.h>
- #include <OWORLD.h>
- #include <ONATION.h>
- #include <OU_MARI.h>
- #include <OSPY.h>
- #include <OGAME.h>
- #include <OTOWN.h>
- #include <OF_CAMP.h>
- #include <OF_MONS.h>
- #include <OEFFECT.h>
- #include <OMONSRES.h>
- #include <OREBEL.h>
- #include <OSERES.h>
- #include <OSYS.h>
- #include <OWARPT.h>
- #ifdef NO_DEBUG_UNIT
- #undef err_when
- #undef err_here
- #undef err_if
- #undef err_else
- #undef err_now
- #define err_when(cond)
- #define err_here()
- #define err_if(cond)
- #define err_else
- #define err_now(msg)
- #undef DEBUG
- #endif
- //----------------- Begin of function Unit::update_attack_path_dist -----------------//
- // return 1 if it is time to update result path
- // return 0 otherwise
- //
- int Unit::update_attack_path_dist()
- {
- if(result_path_dist<=6) //1-6
- {
- return 1;
- }
- else if(result_path_dist<=10) // 8, 10
- {
- return !((result_path_dist-6)%2);
- }
- else if(result_path_dist<=20) // 15, 20
- {
- return !((result_path_dist-10)%5);
- }
- else if(result_path_dist<=60) // 28, 36, 44, 52, 60
- {
- return !((result_path_dist-20)%8);
- }
- else if(result_path_dist<=90) // 75, 90
- {
- return !((result_path_dist-60)%15);
- }
- else // 110, 130, 150, etc
- {
- return !((result_path_dist-90)%20);
- }
- err_here();
- return 0;
- }
- //---------- End of function Unit::update_attack_path_dist ----------//
- //##### begin trevor 15/8 #######//
- //----------------- Begin of function Unit::hit_target -----------------//
- // The function can be called in by class Bullet since parent and target
- // are specified.
- //
- // [Unit*] parentUnit is the unit attacking
- // [Unit*] taregtUnit is the unit being attacked
- // <int> attackDamage is the damage done to the target Unit
- //
- // ****************************** Warning ***********************************
- // don't use any member variables of this unit. This unit may not be involved
- // in the attack event
- // **************************************************************************
- //
- void Unit::hit_target(Unit* parentUnit, Unit* targetUnit, float attackDamage)
- {
- short parentNationRecno = (parentUnit) ? parentUnit->nation_recno : 0;
- short targetNationRecno = targetUnit->nation_recno;
- //------------------------------------------------------------//
- // if the attacked unit is in defense mode, order other available
- // unit in the same camp to help this unit
- // Note : checking for nation_recno since one unit can attack units
- // in same nation by bullet accidentally
- //------------------------------------------------------------//
- if(parentUnit && parentUnit->cur_action!=SPRITE_DIE && parentUnit->is_visible() &&
- parentNationRecno!=targetNationRecno && parentUnit->nation_can_attack(targetNationRecno) &&
- targetUnit->in_auto_defense_mode())
- {
- err_when(targetUnit->action_misc!=ACTION_MISC_DEFENSE_CAMP_RECNO || !targetUnit->action_misc_para);
- if(!firm_array.is_deleted(targetUnit->action_misc_para))
- {
- Firm *firmPtr = firm_array[targetUnit->action_misc_para];
- if(firmPtr->firm_id==FIRM_CAMP)
- {
- err_when(firmPtr->firm_id!=FIRM_CAMP);
- FirmCamp *campPtr = firmPtr->cast_to_FirmCamp();
- campPtr->defense(parentUnit->sprite_recno);
- }
- }
- else
- targetUnit->clear_unit_defense_mode();
- }
- // ---------- add indicator on the map ----------//
- if( nation_array.player_recno && targetUnit->is_own() )
- war_point_array.add_point(targetUnit->next_x_loc(),targetUnit->next_y_loc());
- //-----------------------------------------------------------------------//
- // decrease the hit points of the target Unit
- //-----------------------------------------------------------------------//
- #define DEFAULT_ARMOR 4
- #define DEFAULT_ARMOR_OVER_ATTACK_SLOW_DOWN (float) DEFAULT_ARMOR / ATTACK_SLOW_DOWN
- #define ONE_OVER_ATTACK_SLOW_DOWN (float) 1/ATTACK_SLOW_DOWN
- #define COMPARE_POINT DEFAULT_ARMOR_OVER_ATTACK_SLOW_DOWN + ONE_OVER_ATTACK_SLOW_DOWN
- //-*********** simulate aat ************-//
- #ifdef DEBUG
- if(!debug_sim_game_type)
- {
- #endif
- if( attackDamage >= COMPARE_POINT )
- targetUnit->hit_points -= attackDamage - DEFAULT_ARMOR_OVER_ATTACK_SLOW_DOWN;
- else
- targetUnit->hit_points -= min(attackDamage,ONE_OVER_ATTACK_SLOW_DOWN); // in case attackDamage = 0, no hit_point is reduced
- #ifdef DEBUG
- }
- #endif
- //-*********** simulate aat ************-//
- Nation *parentNationPtr = parentNationRecno ? nation_array[parentNationRecno] : NULL;
- Nation *targetNationPtr = targetNationRecno ? nation_array[targetNationRecno] : NULL;
- char targetUnitClass = unit_res[targetUnit->unit_id]->unit_class;
- if( targetUnit->hit_points <= 0 )
- {
- targetUnit->hit_points = (float) 0;
- //---- if the unit killed is a human unit -----//
- if( targetUnit->race_id )
- {
- //---- if the unit killed is a civilian unit -----//
- if( targetUnit->is_civilian() )
- {
- if( targetNationRecno )
- {
- targetNationPtr->civilian_killed(targetUnit->race_id, 0);
- targetNationPtr->own_civilian_killed++;
- }
- if(parentUnit && parentNationRecno )
- {
- parentNationPtr->civilian_killed(targetUnit->race_id, 1);
- parentNationPtr->enemy_civilian_killed++;
- }
- }
- else //---- if the unit killed is a soldier -----//
- {
- if( targetNationRecno )
- targetNationPtr->own_soldier_killed++;
- if(parentUnit && parentNationRecno )
- parentNationPtr->enemy_soldier_killed++;
- }
- }
- //--------- if it's a non-human unit ---------//
- else
- {
- switch( unit_res[targetUnit->unit_id]->unit_class )
- {
- case UNIT_CLASS_WEAPON:
- if(parentUnit && parentNationRecno )
- parentNationPtr->enemy_weapon_destroyed++;
- if( targetNationRecno )
- targetNationPtr->own_weapon_destroyed++;
- break;
- case UNIT_CLASS_SHIP:
- if(parentUnit && parentNationRecno )
- parentNationPtr->enemy_ship_destroyed++;
- if( targetNationRecno )
- targetNationPtr->own_ship_destroyed++;
- break;
- }
- //---- if the unit destroyed is a trader or caravan -----//
- if( targetUnit->unit_id == UNIT_CARAVAN || // whoever kills a caravan decrease, who will be resented by all races
- targetUnit->unit_id == UNIT_VESSEL )
- {
- if( targetNationRecno )
- targetNationPtr->civilian_killed(0, 0); // 0-for all races
- if(parentUnit && parentNationRecno )
- parentNationPtr->civilian_killed(0, 1); // 1-is the nation is the attacking one
- }
- }
- return;
- }
- if(parentUnit!=NULL && parentNationRecno!=targetNationRecno)
- parentUnit->gain_experience(); // gain experience to increase combat level
- //-----------------------------------------------------------------------//
- // action of the target to take
- //-----------------------------------------------------------------------//
- if( !parentUnit ) // do nothing if parent is dead
- return;
- if( parentUnit->cur_action==SPRITE_DIE ) // skip for explosive cart
- {
- err_when(parentUnit->unit_id!=UNIT_EXPLOSIVE_CART);
- return;
- }
- if( targetNationRecno == parentNationRecno ) // the target and the attacker's nations are different (it's possible that when a unit who has just changed nation has its bullet hitting its own nation)
- return;
- //------- two nations at war ---------//
- if( parentNationRecno && targetNationRecno )
- {
- parentNationPtr->set_at_war_today();
- targetNationPtr->set_at_war_today(parentUnit->sprite_recno);
- }
- //-------- increase battling fryhtan score --------//
- if( targetUnitClass==UNIT_CLASS_MONSTER && parentNationRecno )
- {
- parentNationPtr->kill_monster_score += (float) 0.1;
- }
- //------ call target unit being attack functions -------//
- if( targetNationRecno )
- {
- targetNationPtr->being_attacked(parentNationRecno);
- if( targetUnit->ai_unit )
- {
- if( targetUnit->rank_id >= RANK_GENERAL )
- targetUnit->ai_leader_being_attacked(parentUnit->sprite_recno);
- if( unit_res[targetUnit->unit_id]->unit_class == UNIT_CLASS_SHIP )
- ((UnitMarine*)targetUnit)->ai_ship_being_attacked(parentUnit->sprite_recno);
- }
- //--- if a member in a troop is under attack, ask for other troop members to help ---//
- if( info.game_date%2 == sprite_recno%2 )
- {
- if( targetUnit->leader_unit_recno ||
- (targetUnit->team_info && targetUnit->team_info->member_count > 1) )
- {
- if( !unit_array.is_deleted(parentUnit->sprite_recno) ) // it is possible that parentUnit is dying right now
- {
- targetUnit->ask_team_help_attack(parentUnit);
- }
- }
- }
- }
- //--- increase reputation of the nation that attacks monsters ---//
- else if( targetUnitClass == UNIT_CLASS_MONSTER )
- {
- if( parentNationRecno )
- parentNationPtr->change_reputation(REPUTATION_INCREASE_PER_ATTACK_MONSTER);
- }
- //------------------------------------------//
- if(!targetUnit->can_attack()) // no action if the target unit is unable to attack
- return;
- err_when(!targetUnit->can_attack());
- targetUnit->unit_auto_guarding(parentUnit);
- }
- //---------- End of function Unit::hit_target ----------//
- //##### end trevor 15/8 #######//
- //----------- Begin of function Unit::unit_auto_guarding ---------------//
- // the unit attacks the unit attacking it
- //
- // <Unit*> attackUnit - the unit attacking this unit
- //
- void Unit::unit_auto_guarding(Unit *attackUnit)
- {
- if( force_move_flag )
- return;
- //##### begin trevor 9/10 ########//
- //---------------------------------------//
- //
- // If the aggressive_mode is off, then don't
- // fight back when the unit is moving, only
- // fight back when the unit is already fighting
- // or is idle.
- //
- //---------------------------------------//
- if( !aggressive_mode && cur_action != SPRITE_ATTACK &&
- cur_action != SPRITE_IDLE )
- {
- return;
- }
- //##### begin trevor 9/10 ########//
- //--------------------------------------------------------------------//
- // decide attack or not
- //--------------------------------------------------------------------//
- int changeToAttack=0;
- if(cur_action==SPRITE_ATTACK || (sprite_info->need_turning && cur_action==SPRITE_TURN &&
- (abs(next_x_loc()-action_x_loc)<attack_range || abs(next_y_loc()-action_y_loc)<attack_range)))
- {
- err_when(cur_x!=next_x || cur_y!=next_y);
- if(action_mode!=ACTION_ATTACK_UNIT)
- changeToAttack++; //else continue to attack the target unit
- else
- {
- err_when(!action_para);
- if(unit_array.is_deleted(action_para))
- changeToAttack++; // attack new target
- }
- }
- else if(cur_action!=SPRITE_DIE)// && abs(cur_x-next_x)<spriteInfo->speed && abs(cur_y-next_y)<spriteInfo->speed)
- {
- changeToAttack++;
- /*if(!ai_unit) // player unit
- {
- if(action_mode!=ACTION_ATTACK_UNIT)
- changeToAttack++; //else continue to attack the target unit
- else
- {
- err_when(!action_para);
- if(unit_array.is_deleted(action_para))
- changeToAttack++; // attack new target
- }
- }
- else
- changeToAttack++;*/
- }
- if(!changeToAttack)
- {
- if(ai_unit) // allow ai unit to select target to attack
- {
- //------------------------------------------------------------//
- // conditions to let the unit escape
- //------------------------------------------------------------//
- //-************* codes here ************-//
- //------------------------------------------------------------//
- // select the weaker target to attack first, if more than one
- // unit attack this unit
- //------------------------------------------------------------//
- int attackXLoc = attackUnit->next_x_loc();
- int attackYLoc = attackUnit->next_y_loc();
- int attackDistance = cal_distance(attackXLoc, attackYLoc, attackUnit->sprite_info->loc_width,
- attackUnit->sprite_info->loc_height);
- if(attackDistance==1) // only consider close attack
- {
- err_when(!action_para || unit_array.is_deleted(action_para));
- Unit *targetUnit = unit_array[action_para];
- if(targetUnit->hit_points > attackUnit->hit_points) // the new attacker is weaker
- attack_unit(attackUnit->sprite_recno);
- }
- }
- return;
- }
- //--------------------------------------------------------------------//
- // cancel AI actions
- //--------------------------------------------------------------------//
- if( ai_action_id )
- nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
- if(in_auto_defense_mode())
- set_search_tries(AUTO_DEFENSE_SEARCH_TRIES);
- if(!attackUnit->is_visible())
- return;
- //--------------------------------------------------------------------------------//
- // checking for ship processing trading
- //--------------------------------------------------------------------------------//
- if(sprite_info->sprite_sub_type=='M') //**** BUGHERE, is sprite_sub_type really representing UNIT_MARINE???
- {
- UnitInfo* unitInfo = unit_res[unit_id];
- if(unitInfo->carry_goods_capacity)
- {
- UnitMarine *shipPtr = (UnitMarine*) this;
- if(shipPtr->auto_mode && shipPtr->stop_defined_num>1)
- {
- int targetXLoc = attackUnit->next_x_loc();
- int targetYLoc = attackUnit->next_y_loc();
- SpriteInfo *targetSpriteInfo = attackUnit->sprite_info;
- int attackDistance = cal_distance(targetXLoc, targetYLoc, targetSpriteInfo->loc_width, targetSpriteInfo->loc_height);
- int maxAttackRange = max_attack_range();
- if(maxAttackRange<attackDistance)
- return; // can't attack the target
- }
- }
- }
- switch(action_mode2)
- {
- case ACTION_AUTO_DEFENSE_DETECT_TARGET: case ACTION_AUTO_DEFENSE_BACK_CAMP:
- action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
- break;
- case ACTION_DEFEND_TOWN_DETECT_TARGET: case ACTION_DEFEND_TOWN_BACK_TOWN:
- action_mode2 = ACTION_DEFEND_TOWN_ATTACK_TARGET;
- break;
- case ACTION_MONSTER_DEFEND_DETECT_TARGET: case ACTION_MONSTER_DEFEND_BACK_FIRM:
- action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
- break;
- }
- //##### trevor 9/10 #######//
- save_original_action();
- //----------------------------------------------------------//
- // set the original location of the attacking target when
- // the attack() function is called, action_x_loc2 & action_y_loc2
- // will change when the unit move, but these two will not.
- //----------------------------------------------------------//
- original_target_x_loc = attackUnit->next_x_loc();
- original_target_y_loc = attackUnit->next_y_loc();
- //##### trevor 9/10 #######//
- if(!unit_array.is_deleted(attackUnit->sprite_recno))
- attack_unit(attackUnit->sprite_recno);
- }
- //---------- End of function Unit::unit_auto_guarding ----------//
- //----------- Begin of function Unit::hit_building ---------------//
- //
- // note: If parentUnit==NULL, the attacking unit is already dead.
- // In range attack, the unit calling this function may not be the
- // attacking unit.
- //
- // <Unit*> parentUnit - the attacking unit
- // <int> target?Loc - the target building location
- // <int> attackDamage - the actual damage made
- //
- // ****************************** Warning ***********************************
- // don't use any member variables of this unit. This unit may not be involved
- // in the attack event
- // **************************************************************************
- //
- void Unit::hit_building(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage)
- {
- Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
- if(locPtr->is_firm())
- hit_firm( attackUnit, targetXLoc, targetYLoc, attackDamage);
- else if( locPtr->is_town() )
- hit_town( attackUnit, targetXLoc, targetYLoc, attackDamage);
- }
- //---------- End of function Unit::hit_building ----------//
- //##### begin trevor 15/8 #######//
- //------------ Begin of function Unit::hit_firm --------------//
- //
- // note: If parentUnit==NULL, the attacking unit is already dead.
- // In range attack, the unit calling this function may not be the
- // attacking unit.
- //
- // <Unit*> attackUnit - the attacking unit
- // <int> target?Loc - the target building location
- // <int> attackDamage - the actual damage made
- //
- // ****************************** Warning ***********************************
- // don't use any member variables of this unit. This unit may not be involved
- // in the attack event
- // **************************************************************************
- //
- void Unit::hit_firm(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage)
- {
- Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
- if(!locPtr->is_firm())
- return; // do nothing if no firm there
- //----------- attack firm ------------//
- err_when(!locPtr->firm_recno());
- Firm *targetFirm = firm_array[locPtr->firm_recno()];
- err_when(!targetFirm);
- //------------------------------------------------------------------------------//
- // change relation to hostile
- // check for NULL to skip unhandled case by bullets
- // check for SPRITE_DIE to skip the case by EXPLOSIVE_CART
- //------------------------------------------------------------------------------//
- if( attackUnit!=NULL && attackUnit->cur_action!=SPRITE_DIE &&
- targetFirm->nation_recno != attackUnit->nation_recno ) // the target and the attacker's nations are different (it's possible that when a unit who has just changed nation has its bullet hitting its own nation)
- {
- if( attackUnit->nation_recno && targetFirm->nation_recno )
- {
- //### trevor 29/9 ###//
- nation_array[attackUnit->nation_recno]->set_at_war_today();
- nation_array[targetFirm->nation_recno]->set_at_war_today(attackUnit->sprite_recno);
- //### trevor 29/9 ###//
- }
- if( targetFirm->nation_recno )
- nation_array[targetFirm->nation_recno]->being_attacked(attackUnit->nation_recno);
- //------------ auto defense -----------------//
- if(attackUnit->is_visible())
- targetFirm->auto_defense(attackUnit->sprite_recno);
- if(attackUnit->nation_recno!=targetFirm->nation_recno)
- attackUnit->gain_experience(); // gain experience to increase combat level
- targetFirm->being_attacked(attackUnit->sprite_recno);
- //------ increase battling fryhtan score -------//
- if( targetFirm->firm_id == FIRM_MONSTER && attackUnit->nation_recno )
- nation_array[attackUnit->nation_recno]->kill_monster_score += (float) 0.01;
- }
- //---------- add indicator on the map ----------//
- // ###### begin Gilbert 6/10 #######//
- if( nation_array.player_recno && targetFirm->own_firm() )
- war_point_array.add_point(targetFirm->center_x, targetFirm->center_y);
- // ###### end Gilbert 6/10 #######//
- //---------- damage to the firm ------------//
- targetFirm->hit_points -= attackDamage/3; // /3 so that it takes longer to destroy a firm
- //######## begin trevor 25/8 ##########//
- if(targetFirm->hit_points <= 0)
- {
- targetFirm->hit_points = (float) 0;
- se_res.sound(targetFirm->center_x, targetFirm->center_y, 1,
- 'F', targetFirm->firm_id, "DIE" );
- if( targetFirm->nation_recno == nation_array.player_recno )
- news_array.firm_destroyed(targetFirm->firm_recno, attackUnit);
- if( targetFirm->nation_recno )
- {
- if( attackUnit->nation_recno )
- nation_array[attackUnit->nation_recno]->enemy_firm_destroyed++;
- if( targetFirm->nation_recno )
- nation_array[targetFirm->nation_recno]->own_firm_destroyed++;
- }
- else if( targetFirm->firm_id == FIRM_MONSTER )
- {
- news_array.monster_firm_destroyed( ((FirmMonster*)targetFirm)->monster_id, targetFirm->center_x, targetFirm->center_y );
- }
- firm_array.del_firm(targetFirm->firm_recno);
- }
- //######## end trevor 25/8 ##########//
- }
- //---------- End of function Unit::hit_firm ----------//
- //--------- Begin of function Unit::hit_town ---------//
- //
- // note: If attackUnit==NULL, the attacking unit is already dead.
- // In range attack, the unit calling this function may not be the
- // attacking unit.
- //
- // <Unit*> attackUnit - the attacking unit
- // <int> target?Loc - the target building location
- // <int> attackDamage - the actual damage made
- //
- // ****************************** Warning ***********************************
- // don't use any member variables of this unit. This unit may not be involved
- // in the attack event
- // **************************************************************************
- //
- void Unit::hit_town(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage)
- {
- Location *locPtr = world.get_loc(targetXLoc, targetYLoc);
- if(!locPtr->is_town())
- return; // do nothing if no town there
- //----------- attack town ----------//
- err_when(!locPtr->town_recno());
- Town *targetTown = town_array[locPtr->town_recno()];
- int targetTownRecno = targetTown->town_recno;
- int targetTownNameId = targetTown->town_name_id;
- int targetTownXLoc = targetTown->center_x;
- int targetTownYLoc = targetTown->center_y;
- // ---------- add indicator on the map ----------//
- // ###### begin Gilbert 6/10 #######//
- if( nation_array.player_recno && targetTown->nation_recno == nation_array.player_recno )
- war_point_array.add_point(targetTown->center_x, targetTown->center_y);
- // ###### end Gilbert 6/10 #######//
- //------------------------------------------------------------------------------//
- // change relation to hostile
- // check for NULL to skip unhandled case by bullets
- // check for SPRITE_DIE to skip the case by EXPLOSIVE_CART
- //------------------------------------------------------------------------------//
- if( attackUnit!=NULL && attackUnit->cur_action!=SPRITE_DIE &&
- targetTown->nation_recno != attackUnit->nation_recno ) // the target and the attacker's nations are different (it's possible that when a unit who has just changed nation has its bullet hitting its own nation)
- {
- int townNationRecno = targetTown->nation_recno;
- //------- change to hostile relation -------//
- if( attackUnit->nation_recno && targetTown->nation_recno )
- {
- //### trevor 29/9 ###//
- nation_array[attackUnit->nation_recno]->set_at_war_today();
- nation_array[targetTown->nation_recno]->set_at_war_today(attackUnit->sprite_recno);
- //### trevor 29/9 ###//
- }
- if( targetTown->nation_recno)
- {
- nation_array[targetTown->nation_recno]->being_attacked(attackUnit->nation_recno);
- }
- news_array.disable(); // don't add the town abandon news that might be called by Town::dec_pop() as the town is actually destroyed not abandoned
- targetTown->being_attacked(attackUnit->sprite_recno, attackDamage);
- news_array.enable();
- //------ if the town is destroyed, add a news --------//
- if( town_array.is_deleted(targetTownRecno) &&
- townNationRecno == nation_array.player_recno )
- {
- news_array.town_destroyed(targetTownNameId, targetTownXLoc, targetTownYLoc, attackUnit);
- }
- //---------- gain experience --------//
- if(attackUnit->nation_recno!=targetTown->nation_recno)
- attackUnit->gain_experience(); // gain experience to increase combat level
- //------------ auto defense -----------------//
- if( !firm_array.is_deleted(targetTownRecno) )
- targetTown->auto_defense(attackUnit->sprite_recno);
- }
- }
- //---------- End of function Unit::hit_town ----------//
- //##### end trevor 15/8 #######//
- //--------- Begin of function Unit::hit_wall -----------//
- //
- // <Unit*> attackUnit - the attacking unit
- // <int> target?Loc - the targeted wall location
- // <int> attackDamage - the actual damage made
- //
- // ****************************** Warning ***********************************
- // don't use any member variables of this unit. This unit may not be involved
- // in the attack event
- // **************************************************************************
- //
- void Unit::hit_wall(Unit* attackUnit, int targetXLoc, int targetYLoc, float attackDamage)
- {
- Location *locPtr = world.get_loc(targetXLoc, targetYLoc);
- err_when(!locPtr->is_wall());
- //######## begin trevor 25/6 #########//
- /*
- if(attackUnit!=NULL)
- attackUnit->change_relation(attackUnit->nation_recno, locPtr->wall_nation_recno(), NATION_HOSTILE);
- */
- //######## end trevor 25/6 #########//
- if( !locPtr->attack_wall((int)attackDamage) )
- world.correct_wall(targetXLoc, targetYLoc);
- }
- //---------- End of function Unit::hit_wall ----------//
- //--------- Begin of function Unit::cal_distance ---------//
- // calculate the distance from this unit to the target
- // (assume the size of this unit is a square)
- //
- // <int> targetXLoc - x location of the target
- // <int> targetYLoc - y location of the target
- // <int> targetWidth - target width
- // <int> targetHeight - target height
- //
- int Unit::cal_distance(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight)
- {
- int curXLoc = next_x_loc();
- int curYLoc = next_y_loc();
- int dispX=0, dispY=0;
- if(curXLoc<targetXLoc)
- dispX = (targetXLoc - curXLoc - sprite_info->loc_width) + 1;
- else if((dispX=curXLoc-targetXLoc-targetWidth+1)<0)
- dispX = 0;
- err_when(dispX<0 || dispX>MAX_WORLD_X_LOC);
- if(curYLoc<targetYLoc)
- dispY = (targetYLoc - curYLoc - sprite_info->loc_height) + 1;
- else if((dispY=curYLoc-targetYLoc-targetHeight+1)<0)
- {
- err_when(mobile_type!=UNIT_AIR && !dispX); // inside the target
- return dispX;
- }
- err_when(dispY<0 || dispY>MAX_WORLD_Y_LOC);
- return (dispX>=dispY)? dispX : dispY;
- }
- //----------- End of function Unit::cal_distance -----------//
- //------------ Begin of function Unit::actual_damage --------------//
- //
- // return: return the actual hit damage this unit can do to a target.
- //
- float Unit::actual_damage()
- {
- AttackInfo *attackInfo = attack_info_array+cur_attack;
- int attackDamage = attackInfo->attack_damage;
- //-------- pierce damage --------//
- attackDamage += m.random(3) + attackInfo->pierce_damage
- * m.random(skill.combat_level-attackInfo->combat_level)
- / (100-attackInfo->combat_level);
- //--- if this unit is led by a general, its attacking ability is influenced by the general ---//
- //
- // The unit's attacking ability is increased by a percentage equivalent to
- // the leader unit's leadership.
- //
- //------------------------------------------------------------------------//
- if( leader_unit_recno )
- {
- if( unit_array.is_deleted(leader_unit_recno) )
- {
- leader_unit_recno = 0;
- }
- else
- {
- Unit* leaderUnit = unit_array[leader_unit_recno];
- int leaderXLoc, leaderYLoc;
- if( leaderUnit->is_visible() )
- {
- leaderXLoc = cur_x_loc();
- leaderYLoc = cur_y_loc();
- }
- else if( leaderUnit->unit_mode == UNIT_MODE_OVERSEE )
- {
- Firm* firmPtr = firm_array[leaderUnit->unit_mode_para];
- leaderXLoc = firmPtr->center_x;
- leaderYLoc = firmPtr->center_y;
- }
- else
- leaderXLoc = -1;
- if( leaderXLoc >= 0 &&
- m.points_distance(cur_x_loc(), cur_y_loc(), leaderXLoc, leaderYLoc) <= EFFECTIVE_LEADING_DISTANCE )
- {
- attackDamage += attackDamage * leaderUnit->skill.skill_level / 100;
- }
- }
- }
- return (float) attackDamage / ATTACK_SLOW_DOWN; // lessen all attacking damages, thus slowing down all battles.
- }
- //------------ End of function Unit::actual_damage --------------//
- //--------- Begin of function Unit::gain_experience ---------//
- void Unit::gain_experience()
- {
- if(unit_res[unit_id]->unit_class != UNIT_CLASS_HUMAN)
- return; // no experience gain if unit is not human
- //---- increase the unit's contribution to the nation ----//
- if( nation_contribution < MAX_NATION_CONTRIBUTION )
- {
- nation_contribution++;
- err_when( nation_contribution < 0 ); // overflow
- }
- //------ increase combat skill -------//
- err_when(skill.combat_level<0 || skill.combat_level>100);
- inc_minor_combat_level(6);
- //--- if this is a soldier led by a commander, increase the leadership of its commander -----//
- if( leader_unit_recno )
- {
- Unit* leaderUnit = unit_array[leader_unit_recno];
- int leaderXLoc= -1, leaderYLoc;
- if( leaderUnit->is_visible() )
- {
- leaderXLoc = cur_x_loc();
- leaderYLoc = cur_y_loc();
- }
- else if( leaderUnit->unit_mode == UNIT_MODE_OVERSEE )
- {
- Firm* firmPtr = firm_array[leaderUnit->unit_mode_para];
- leaderXLoc = firmPtr->center_x;
- leaderYLoc = firmPtr->center_y;
- }
- else
- leaderXLoc = -1;
- if( leaderXLoc >= 0 &&
- m.points_distance( cur_x_loc(), cur_y_loc(), leaderXLoc, leaderYLoc ) <= EFFECTIVE_LEADING_DISTANCE )
- {
- leaderUnit->inc_minor_skill_level(1);
- //-- give additional increase if the leader has skill potential on leadership --//
- if( leaderUnit->skill.skill_potential > 0 )
- {
- if( m.random(10-leaderUnit->skill.skill_potential/10)==0 )
- leaderUnit->inc_minor_skill_level(5);
- }
- }
- //--- if this soldier has leadership potential and is led by a commander ---//
- //--- he learns leadership by watching how the commander commands the troop --//
- if( skill.skill_potential > 0 )
- {
- if( m.random(10-skill.skill_potential/10)==0 )
- inc_minor_skill_level(5);
- }
- }
- }
- //------------ End of function Unit::gain_experience --------------//
- //--------- Begin of function Unit::can_attack ---------//
- // return 1 if can attack
- // return 0 otherwise
- //
- /*int Unit::can_attack()
- {
- return (can_attack_flag && attack_count);
- }*/
- //------------ End of function Unit::can_attack --------------//
- //--------- Begin of function Unit::nation_can_attack ---------//
- // return 1 for able to attack this nation i.e. relation is not
- // friendly or alliance
- // return 0 otherwise
- //
- // Whether this unit can attack others with the specified nation recno
- //
- // <short> nationRecno - nation recno to be checked
- //
- int Unit::nation_can_attack(short nationRecno)
- {
- if(!ai_unit)
- {
- //return 1;
- if( game.game_mode == GAME_TEST ) // in testing games, player units can attack their own units
- return 1;
- else
- return nationRecno!=nation_recno; // able to attack all nation except our own nation
- }
- else if(nation_recno == nationRecno)
- return 0; // ai unit don't attack its own nation, except special order
- if(!nation_recno || !nationRecno)
- return 1; // true if either nation is independent
- Nation *nationPtr = nation_array[nation_recno];
- char relatinStatus = nationPtr->get_relation_status(nationRecno);
- if(relatinStatus==NATION_FRIENDLY || relatinStatus==NATION_ALLIANCE)
- return 0;
- return 1;
- }
- //------------ End of function Unit::nation_can_attack --------------//
- //--------- Begin of function Unit::independent_nation_can_attack ---------//
- // Note: this unit should be an independent unit
- //
- // Should this independent unit attack other units with specified nation recno
- //
- // return 1 if decision is attacking
- // return 0 otherwise
- //
- // <short> nationRecno - nation recno to be checked
- //
- int Unit::independent_nation_can_attack(short nationRecno)
- {
- err_when(nation_recno);
- Town *townPtr;
- FirmMonster *firmMonster;
- Rebel *rebelPtr;
- switch(unit_mode)
- {
- case UNIT_MODE_DEFEND_TOWN:
- err_when(unit_mode_para<=0);
- if(town_array.is_deleted(unit_mode_para))
- return 0; // don't attack independent unit with no town
- townPtr = town_array[unit_mode_para];
- if( !townPtr->is_hostile_nation(nationRecno) )
- return 0; // false if the indepentent unit don't want to attack us
- break;
- case UNIT_MODE_REBEL:
- if(rebel_array.is_deleted(unit_mode_para))
- return 0;
- rebelPtr = rebel_array[unit_mode_para];
- if( !rebelPtr->is_hostile_nation(nationRecno) )
- return 0;
- break;
- //######## begin trevor 22/8 ##########//
- case UNIT_MODE_MONSTER:
- if( unit_mode_para==0 )
- return nationRecno; // attack anything that is not independent
- firmMonster = (FirmMonster*) firm_array[unit_mode_para];
- err_when( firmMonster->firm_id != FIRM_MONSTER );
- if( !firmMonster->is_hostile_nation(nationRecno) )
- return 0; // false if the indepentent unit don't want to attack us
- break;
- //######## end trevor 22/8 ##########//
- default:
- return 0;
- }
- return 1;
- }
- //------------ End of function Unit::independent_nation_can_attack --------------//
- //--------- Begin of function Unit::choose_best_attack_mode ---------//
- // if the unit has more than one attack mode, select the suitable mode
- // to attack the target
- //
- // <int> attackDistance - the distance from the target
- // [char] targetMobileType - the target's mobile_type (default: UNIT_LAND)
- //
- void Unit::choose_best_attack_mode(int attackDistance, char targetMobileType)
- {
- //------------ enable/disable range attack -----------//
- //cur_attack = 0;
- //return;
- //-------------------- define parameters -----------------------//
- UCHAR attackModeBeingUsed = cur_attack;
- err_when(attackModeBeingUsed<0 || attackModeBeingUsed>MAX_UNIT_ATTACK_TYPE);
- //UCHAR maxAttackRangeMode = 0;
- UCHAR maxAttackRangeMode = cur_attack;
- AttackInfo* attackInfoMaxRange = attack_info_array;
- AttackInfo* attackInfoChecking;
- AttackInfo* attackInfoSelected = attack_info_array+cur_attack;
- //--------------------------------------------------------------//
- // If targetMobileType==UNIT_AIR or mobile_type==UNIT_AIR,
- // force to use range_attack.
- // If there is no range_attack, return 0, i.e. cur_attack=0
- //--------------------------------------------------------------//
- if(attack_count>1)
- {
- int canAttack = 0;
- int checkingDamageWeight, selectedDamageWeight;
- for(UCHAR i=0; i<attack_count; i++)
- {
- if(attackModeBeingUsed==i)
- continue; // it is the mode already used
- attackInfoChecking = attack_info_array+i;
- if(can_attack_with(attackInfoChecking) && attackInfoChecking->attack_range>=attackDistance)
- {
- //-------------------- able to attack ----------------------//
- canAttack = 1;
- if(attackInfoSelected->attack_range<attackDistance)
- {
- attackModeBeingUsed = UCHAR(i);
- attackInfoSelected = attackInfoChecking;
- continue;
- }
-
- checkingDamageWeight = attackInfoChecking->attack_damage;
- selectedDamageWeight = attackInfoSelected->attack_damage;
- if(attackDistance==1 && (targetMobileType!=UNIT_AIR && mobile_type!=UNIT_AIR))
- {
- //------------ force to use close attack if possible -----------//
- if(attackInfoSelected->attack_range==attackDistance)
- {
- if(attackInfoChecking->attack_range==attackDistance && checkingDamageWeight>selectedDamageWeight)
- {
- attackModeBeingUsed = UCHAR(i); // choose the one with strongest damage
- attackInfoSelected = attackInfoChecking;
- }
- continue;
- }
- else if(attackInfoChecking->attack_range==1)
- {
- attackModeBeingUsed = UCHAR(i);
- attackInfoSelected = attackInfoChecking;
- continue;
- }
- }
-
- //----------------------------------------------------------------------//
- // further selection
- //----------------------------------------------------------------------//
- if(checkingDamageWeight == selectedDamageWeight)
- {
- if(attackInfoChecking->attack_range<attackInfoSelected->attack_range)
- {
- if(attackInfoChecking->attack_range>1 || (targetMobileType!=UNIT_AIR && mobile_type!=UNIT_AIR))
- {
- //--------------------------------------------------------------------------//
- // select one with shortest attack_range
- //--------------------------------------------------------------------------//
- attackModeBeingUsed = UCHAR(i);
- attackInfoSelected = attackInfoChecking;
- }
- }
- }
- else
- {
- //--------------------------------------------------------------------------//
- // select one that can do the attacking immediately with the strongest damage point
- //--------------------------------------------------------------------------//
- attackModeBeingUsed = UCHAR(i);
- attackInfoSelected = attackInfoChecking;
- }
- }
-
- if(!canAttack)
- {
- //------------------------------------------------------------------------------//
- // if unable to attack the target, choose the mode with longer attack_range and
- // heavier damage
- //------------------------------------------------------------------------------//
- if(can_attack_with(attackInfoChecking) &&
- (attackInfoChecking->attack_range>attackInfoMaxRange->attack_range ||
- (attackInfoChecking->attack_range==attackInfoMaxRange->attack_range &&
- attackInfoChecking->attack_damage>attackInfoMaxRange->attack_damage)))
- {
- maxAttackRangeMode = UCHAR(i);
- attackInfoMaxRange = attackInfoChecking;
- }
- }
- }
- if(canAttack)
- cur_attack = attackModeBeingUsed; // choose the strongest damage mode if able to attack
- else
- cur_attack = maxAttackRangeMode; // choose the longest attack range if unable to attack
- attack_range = attack_info_array[cur_attack].attack_range;
- err_when(final_dir<0 || final_dir>=MAX_SPRITE_DIR_TYPE);
- err_when(cur_attack>=attack_count || cur_attack<0);
- }
- else
- {
- cur_attack = 0; // only one mode is supported
- attack_range = attack_info_array[0].attack_range;
- return;
- }
- }
- //---------- End of function Unit::choose_best_attack_mode ----------//
- //------ Begin of function Unit::set_attack_dir ---------//
- // set direction for attacking
- //
- // <short> curX - x location of the unit
- // <short> curY - y location of the unit
- // <short> targetX - x location of the target
- // <short> targetY - y location of the target
- //
- void Unit::set_attack_dir(short curX, short curY, short targetX, short targetY)
- {
- UCHAR targetDir = get_dir(curX, curY, targetX, targetY);
- if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP)
- {
- UCHAR attackDir1, attackDir2;
- attackDir1 = (targetDir+2)%MAX_SPRITE_DIR_TYPE;
- attackDir2 = (targetDir+6)%MAX_SPRITE_DIR_TYPE;
- if((attackDir1+8-final_dir)%MAX_SPRITE_DIR_TYPE <= (attackDir2+8-final_dir)%MAX_SPRITE_DIR_TYPE)
- final_dir = attackDir1;
- else
- final_dir = attackDir2;
- attack_dir = targetDir;
- err_when(attack_dir<0 || attack_dir>=MAX_SPRITE_DIR_TYPE);
- }
- else
- {
- attack_dir = targetDir;
- set_dir(targetDir);
- }
- }
- //---------- End of function Unit::set_attack_dir ----------//
- //--------- Begin of function Unit::set_unreachable_location ---------//
- // used to set the bit in the unreachable_flag (16 bits)
- //
- // The 16 bits of the flag are used to represent the 16 location of a unit
- // as follows:
- //
- // 1 2 3 4 where x is the upper left corner of the unit.
- // 5 x 6 7 For 1x1 unit, 1,2,3,5,6,8,9,10 are meaningful
- // 8 9 10 11 For 2x2 unit, 1,2,3,4,5,7,8,11,12,13,14,15 are meaningful
- // 12 13 14 15
- //
- void Unit::set_unreachable_location(int xLoc, int yLoc)
- {
- static unsigned short bitFlag[16] = {0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
- 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000};
- /*int curXLoc = next_x_loc();
- int curYLoc = next_y_loc();
- int xDist = xLoc-curXLoc+1;
- int yDist = yLoc-curYLoc+1;
- err_when(xDist<0 || xDist>3 || yDist<0 || yDist>3);
- char bitNo = yDist*4 + xDist;
- err_when(bitNo==5);
- if(bitNo>5)
- bitNo--;
- unreachable_flag |= bitFlag[bitNo];*/
- }
- //----------- End of function Unit::set_unreachable_location -----------//
- //--------- Begin of function Unit::check_self_surround ---------//
- // Note : mobile_type used is this unit's mobile_type
- //
- void Unit::check_self_surround()
- {
- /*err_when(sprite_info->loc_height!=sprite_info->loc_width);
- err_when(sprite_info->loc_width<1 || sprite_info->loc_width>2);
-
- Location *locPtr;
- int width = sprite_info->loc_width;
- int curXLoc = next_x_loc();
- int curYLoc = next_y_loc();
- int startCount = (width==1) ? 2 : 5;
- int endCount = (width==1) ? 9 : 16;
- int xShift, yShift;
- self_surround_flag = 0;
- for(int i=startCount; i<=endCount; i++)
- {
- m.cal_move_around_a_point(i, width, width, xShift, yShift);
- locPtr = world.get_loc(curXLoc+xShift, curYLoc+yShift);
-
- if(!locPtr->can_move(mobile_type))
- m.set_surround_bit(self_surround_flag, i-startCount);
- }*/
- }
- //----------- End of function Unit::check_self_surround -----------//
- //----------- Begin of function Unit::cycle_eqv_attack -----------//
- void Unit::cycle_eqv_attack()
- {
- int trial = MAX_UNIT_ATTACK_TYPE+2;
- if( attack_info_array[cur_attack].eqv_attack_next > 0)
- {
- do
- {
- cur_attack = attack_info_array[cur_attack].eqv_attack_next-1;
- err_when(--trial == 0);
- } while( !can_attack_with(cur_attack) );
- }
- else
- {
- if( !can_attack_with(cur_attack) )
- {
- err_here();
- // force to search again
- char attackRange = char(attack_info_array[cur_attack].attack_range);
- err_when(attackRange != attack_range); // redundant check
- AttackInfo *attackInfo = attack_info_array;
- for(int i = 0; i < attack_count; ++i, ++attackInfo)
- {
- if( attackInfo->attack_range >= attackRange &&
- can_attack_with(attackInfo))
- {
- cur_attack = i;
- break;
- }
- err_when(i >= attack_count); // not found
- }
- }
- }
- err_when(cur_attack < 0 || cur_attack >= attack_count);
- }
- //----------- End of function Unit::cycle_eqv_attack -----------//
- //----------- Begin of function Unit::max_attack_range -----------//
- // return the maximum attack range the unit can make
- //
- //
- //
- int Unit::max_attack_range()
- {
- int maxRange=0;
- AttackInfo *attackInfo = attack_info_array;
- for(int i=0; i<attack_count; i++, attackInfo++)
- {
- if(can_attack_with(attackInfo) &&
- attackInfo->attack_range>maxRange)
- maxRange = attackInfo->attack_range;
- }
-
- return maxRange;
- }
- //----------- End of function Unit::max_attack_range -----------//
- //----------- Begin of function Unit::can_attack_with -------//
- int Unit::can_attack_with(int i)
- {
- err_when( i< 0 || i >= attack_count);
- AttackInfo *attackInfo = attack_info_array+i;
- return( skill.combat_level >= attackInfo->combat_level &&
- cur_power >= attackInfo->min_power);
-
- }
- int Unit::can_attack_with(AttackInfo *attackInfo)
- {
- return( skill.combat_level >= attackInfo->combat_level &&
- cur_power >= attackInfo->min_power);
- }
- //----------- End of function Unit::can_attack_with -------//
- //----------- Begin of function Unit::get_hit_x_y -------//
- void Unit::get_hit_x_y(short *xPtr, short *yPtr)
- {
- switch(cur_dir)
- {
- case 0: // north
- *xPtr = cur_x;
- *yPtr = cur_y - ZOOM_LOC_HEIGHT;
- break;
- case 1: // north east
- *xPtr = cur_x + ZOOM_LOC_WIDTH;
- *yPtr = cur_y - ZOOM_LOC_HEIGHT;
- break;
- case 2: // east
- *xPtr = cur_x + ZOOM_LOC_WIDTH;
- *yPtr = cur_y;
- break;
- case 3: // south east
- *xPtr = cur_x + ZOOM_LOC_WIDTH;
- *yPtr = cur_y + ZOOM_LOC_HEIGHT;
- break;
- case 4: // south
- *xPtr = cur_x;
- *yPtr = cur_y + ZOOM_LOC_HEIGHT;
- break;
- case 5: // south west
- *xPtr = cur_x - ZOOM_LOC_WIDTH;
- *yPtr = cur_y + ZOOM_LOC_HEIGHT;
- break;
- case 6: // west
- *xPtr = cur_x - ZOOM_LOC_WIDTH;
- *yPtr = cur_y;
- break;
- case 7: // north west
- *xPtr = cur_x - ZOOM_LOC_WIDTH;
- *yPtr = cur_y - ZOOM_LOC_HEIGHT;
- break;
- default:
- err_here();
- *xPtr = cur_x;
- *yPtr = cur_y;
- }
- }
- //----------- End of function Unit::get_hit_x_y -------//
- //----------- Begin of function Unit::add_close_attack_effect -------//
- void Unit::add_close_attack_effect()
- {
- short effectId = (attack_info_array+cur_attack)->effect_id;
- if( effectId )
- {
- short x,y;
- get_hit_x_y(&x, &y);
- Effect::create(effectId, x, y, SPRITE_IDLE, cur_dir, mobile_type == UNIT_AIR ? 8 : 2, 0);
- }
- }
- //----------- End of function Unit::add_close_attack_effect -------//
- //----------- Begin of function Unit::is_action_attack -------//
- // check whether the unit carrys on attacking action
- //
- int Unit::is_action_attack()
- {
- switch(action_mode2)
- {
- case ACTION_ATTACK_UNIT:
- case ACTION_ATTACK_FIRM:
- case ACTION_ATTACK_TOWN:
- case ACTION_ATTACK_WALL:
- case ACTION_AUTO_DEFENSE_ATTACK_TARGET:
- case ACTION_AUTO_DEFENSE_DETECT_TARGET:
- case ACTION_AUTO_DEFENSE_BACK_CAMP:
- case ACTION_DEFEND_TOWN_ATTACK_TARGET:
- case ACTION_DEFEND_TOWN_DETECT_TARGET:
- case ACTION_DEFEND_TOWN_BACK_TOWN:
- case ACTION_MONSTER_DEFEND_ATTACK_TARGET:
- case ACTION_MONSTER_DEFEND_DETECT_TARGET:
- case ACTION_MONSTER_DEFEND_BACK_FIRM:
- return 1;
-
- default: return 0;
- }
- return 0;
- }
- //----------- End of function Unit::is_action_attack -------//
|