void fighter::ai() { if(check_bit(attributes, DEAD) || check_bit(attributes, FRIENDLY)) return; calc_lightmap(); int targetx, targety; if(lightmap->data[curr_level->guy->y][curr_level->guy->x] == 1) { targetx = curr_level->guy->x; targety = curr_level->guy->y; } else { return; // targetx = x; // targety = y; } if(a_star(targetx, targety)) { if(is_monster(moves[0]->x, moves[0]->y)) { int monst = is_monster(moves[0]->x, moves[0]->y) - 1; attack_something(curr_level->monsters[monst]); } if(curr_level->guy->x == moves[0]->x && curr_level->guy->y == moves[0]->y) attack_something(curr_level->guy); if(good_move(moves[0]->x, moves[0]->y)) { x = moves[0]->x; y = moves[0]->y; } while(moves.size() > 0) moves.erase(moves.begin()); } return; }
//------- Begin of function Firm::being_killed ------// // // <BaseObj*> attackerObj - this can be NULL if the attacker no longer // exists (the damage is caused by a bullet.) // void Firm::being_killed(BaseObj* attackerObj) { se_res.sound(center_x, center_y, 1, 'F', firm_id, "DIE" ); if( nation_recno == nation_array.player_recno && attackerObj ) //BUGHERE news_array.firm_destroyed(firm_recno, attackerObj); // ######## begin Gilbert 17/6 ########// if( nation_recno == 0 && firm_id == FIRM_LAIR && is_monster() ) { news_array.monster_firm_destroyed( monster_id(), center_x, center_y ); } // ######## end Gilbert 17/6 ########// if( nation_recno ) { if( attackerObj && attackerObj->nation_recno ) nation_array[attackerObj->nation_recno]->enemy_firm_destroyed++; if( nation_recno ) nation_array[nation_recno]->own_firm_destroyed++; } //-----------------------------------------// if( attackerObj && attackerObj->nation_recno ) { Nation* attackerNation = nation_array[attackerObj->nation_recno]; //-- destroying a monster firm raise the attacking nation's reputation --// if( is_monster() ) { float repIncrease = (float) max_hit_points() / 600; //-- if the lair is enslaving the towns, increase the reputation bonus --// if( cast_to_FirmLair() ) { int tributeAmount = cast_to_FirmLair()->collect_town_tribute(0); repIncrease += (float) tributeAmount / 600; } attackerNation->change_reputation(repIncrease); //--- when destroying an enslaving Fryhtan lair, the independent towns enslaved by it will reduce its resistance towards you by 30 points ---// if( cast_to_FirmLair() ) { int i; Town* townPtr; for( i=0 ; i<linked_town_count ; i++ ) { if(town_array.is_deleted(linked_town_array[i])) continue; townPtr = town_array[linked_town_array[i]]; //--- if it is a linked independent town ---// if( townPtr->nation_recno == 0 && // ####### begin Gilbert 9/3 ########// nation_recno && // ####### end Gilbert 9/3 ########// townPtr->resistance(nation_recno) < MONSTER_COLLECT_TOWN_TRIBUTE_LOYALTY ) { townPtr->change_resistance(attackerObj->nation_recno, -30); } } } } //------ destroyng a building gives money ------// float killMoney = (float) (firm_res[firm_id]->setup_cost + firm_recno%100) / 3; // add some randomness attackerNation->add_income( INCOME_TREASURE, killMoney ); attackerNation->increased_cash = killMoney; } firm_array.del_firm(firm_recno); }
//----- Begin of function Nation::think_demand_tribute_aid -----// // // Demand tribute when the nation's economy is good and its // military is weak. // int Nation::think_demand_tribute_aid() { if( info.game_date < info.game_start_date + 180 + nation_recno*50 ) // don't ask for tribute too soon, as in the beginning, the ranking are all the same for all nations return 0; //--------------------------------------// Nation* nationPtr; int totalNation=nation_array.size(); int nationRecno=m.random(totalNation)+1; int curRating, requestRating; int talkId; int ourMilitary = military_rank_rating(); int ourEconomy = economic_rank_rating(); for( int i=totalNation ; i>0 ; i-- ) { if( ++nationRecno > totalNation ) nationRecno = 1; if( nation_array.is_deleted(nationRecno) || nationRecno==nation_recno ) continue; nationPtr = nation_array[nationRecno]; //-- only demand tribute from non-friendly nations --// if( get_relation(nationRecno)->status <= RELATION_NEUTRAL ) talkId = TALK_DEMAND_TRIBUTE; else talkId = TALK_DEMAND_AID; //-----------------------------------------------// float fixedExpense = fixed_expense_365days(); if( talkId == TALK_DEMAND_TRIBUTE ) { if( !should_diplomacy_retry(talkId, nationRecno) ) continue; curRating = ourMilitary - nationPtr->military_rank_rating(); //---- if this is a Fryhtan nation, the tendency to request tribute is higher -----// if( is_monster() && nationPtr->is_human() ) // and the target is a human nation { curRating *= 2; //-- if we are running low of live points, it's time to kill somebody --// if( live_points < 500 * (100+pref_live_points_reserve) / 100 ) curRating *= 2; } if( curRating < 0 ) continue; //----------------------------------------------// // // Some nation will actually consider the ability // of the target nation to pay tribute, so nation // will not and just ask anyway. // //----------------------------------------------// if( pref_economic_development > 50 ) { int addRating = nationPtr->economic_rank_rating()-ourEconomy; if( addRating > 0 ) curRating += addRating; } requestRating = 20 + trade_rating(nationRecno)/2 + (100-pref_peacefulness)/3; if( cash < fixedExpense && fixedExpense != 0 ) requestRating -= int( (float) requestRating * cash / fixedExpense); } else { if( cash >= fixedExpense ) continue; if( cash > fixedExpense * (50+pref_cash_reserve) / 300 && // if the nation is runing short of cash, don't wait a while until next retry, retry immediately !should_diplomacy_retry(talkId, nationRecno) ) { continue; } //----- only ask for aid when the nation is short of cash ----// curRating = (ourMilitary - nationPtr->military_rank_rating())/2 + ( nationPtr->economic_rank_rating()-ourEconomy ); requestRating = 20 + 50 * (int)(cash / fixedExpense); } //----- if the target is a human player's nation -----// if( !nationPtr->is_ai() ) { switch( config.ai_aggressiveness ) { case OPTION_NONE: requestRating += 60; // don't go against the player too easily break; case OPTION_LOW: requestRating += 40; // don't go against the player too easily break; case OPTION_HIGH: requestRating -= 20; break; case OPTION_VERY_HIGH: requestRating -= 40; break; } //--- if the nation has plenty of cash, demand from it ----// if( nationPtr->cash > cash && config.ai_aggressiveness >= OPTION_HIGH ) { requestRating -= (int) (nationPtr->cash - cash)/500; } } //--------------------------------------// if( curRating > requestRating ) { int tributeAmount; if( curRating - requestRating > 120 ) tributeAmount = 4000; else if( curRating - requestRating > 80 ) tributeAmount = 3000; else if( curRating - requestRating > 40 ) tributeAmount = 2000; else if( curRating - requestRating > 20 ) tributeAmount = 1000; else tributeAmount = 500; //------ stop in here if in tutorial mode -----// if( game.game_mode != GAME_TUTORIAL ) { cash += tributeAmount; return 0; } talk_res.ai_send_talk_msg(nationRecno, nation_recno, talkId, tributeAmount); return 1; } } return 0; }
/** * Attempts to harm a creature with a projectile. * * @param source Pointer to the creature who shot the projectile. * @param attack A structure describing the attack and its results. */ void Creature::deal_projectile_attack( Creature *source, dealt_projectile_attack &attack ) { const double missed_by = attack.missed_by; if( missed_by >= 1.0 ) { // Total miss return; } const projectile &proj = attack.proj; dealt_damage_instance &dealt_dam = attack.dealt_dam; const auto &proj_effects = proj.proj_effects; const bool u_see_this = g->u.sees(*this); const int avoid_roll = dodge_roll(); // Do dice(10, speed) instead of dice(speed, 10) because speed could potentially be > 10000 const int diff_roll = dice( 10, proj.speed ); // Partial dodge, capped at [0.0, 1.0], added to missed_by const double dodge_rescaled = avoid_roll / static_cast<double>( diff_roll ); const double goodhit = missed_by + std::max( 0.0, std::min( 1.0, dodge_rescaled ) ) ; if( goodhit >= 1.0 ) { // "Avoid" rather than "dodge", because it includes removing self from the line of fire // rather than just Matrix-style bullet dodging if( source != nullptr && g->u.sees( *source ) ) { add_msg_player_or_npc( m_warning, _("You avoid %s projectile!"), _("<npcname> avoids %s projectile."), source->disp_name(true).c_str() ); } else { add_msg_player_or_npc( m_warning, _("You avoid an incoming projectile!"), _("<npcname> avoids an incoming projectile.") ); } attack.missed_by = 1.0; // Arbitrary value return; } // Bounce applies whether it does damage or not. if( proj.proj_effects.count( "BOUNCE" ) ) { add_effect( effect_bounced, 1_turns ); } body_part bp_hit; double hit_value = missed_by + rng_float(-0.5, 0.5); // Headshots considered elsewhere if( hit_value <= 0.4 ) { bp_hit = bp_torso; } else if (one_in(4)) { if( one_in(2)) { bp_hit = bp_leg_l; } else { bp_hit = bp_leg_r; } } else { if( one_in(2)) { bp_hit = bp_arm_l; } else { bp_hit = bp_arm_r; } } double damage_mult = 1.0; std::string message = ""; game_message_type gmtSCTcolor = m_neutral; if( goodhit < accuracy_headshot ) { message = _("Headshot!"); gmtSCTcolor = m_headshot; damage_mult *= rng_float(1.95, 2.05); bp_hit = bp_head; // headshot hits the head, of course } else if( goodhit < accuracy_critical ) { message = _("Critical!"); gmtSCTcolor = m_critical; damage_mult *= rng_float(1.5, 2.0); } else if( goodhit < accuracy_goodhit ) { message = _("Good hit!"); gmtSCTcolor = m_good; damage_mult *= rng_float(1, 1.5); } else if( goodhit < accuracy_standard ) { damage_mult *= rng_float(0.5, 1); } else if( goodhit < accuracy_grazing ) { message = _("Grazing hit."); gmtSCTcolor = m_grazing; damage_mult *= rng_float(0, .25); } if( source != nullptr && !message.empty() ) { source->add_msg_if_player(m_good, message.c_str()); } attack.missed_by = goodhit; // copy it, since we're mutating damage_instance impact = proj.impact; if( damage_mult > 0.0f && proj_effects.count( "NO_DAMAGE_SCALING" ) ) { damage_mult = 1.0f; } impact.mult_damage(damage_mult); if( proj_effects.count( "NOGIB" ) > 0 ) { float dmg_ratio = (float)impact.total_damage() / get_hp_max( player::bp_to_hp( bp_hit ) ); if( dmg_ratio > 1.25f ) { impact.mult_damage( 1.0f / dmg_ratio ); } } dealt_dam = deal_damage(source, bp_hit, impact); dealt_dam.bp_hit = bp_hit; // Apply ammo effects to target. if (proj.proj_effects.count("FLAME")) { if (made_of( material_id( "veggy" ) ) || made_of( material_id( "cotton" ) ) || made_of( material_id( "wool" ) ) || made_of( material_id( "paper" ) ) || made_of( material_id( "wood" ) ) ) { add_effect( effect_onfire, rng( 8_turns, 20_turns ), bp_hit ); } else if (made_of( material_id( "flesh" ) ) || made_of( material_id( "iflesh" ) ) ) { add_effect( effect_onfire, rng( 5_turns, 10_turns ), bp_hit ); } } else if (proj.proj_effects.count("INCENDIARY") ) { if (made_of( material_id( "veggy" ) ) || made_of( material_id( "cotton" ) ) || made_of( material_id( "wool" ) ) || made_of( material_id( "paper" ) ) || made_of( material_id( "wood" ) ) ) { add_effect( effect_onfire, rng( 2_turns, 6_turns ), bp_hit ); } else if ( (made_of( material_id( "flesh" ) ) || made_of( material_id( "iflesh" ) ) ) && one_in(4) ) { add_effect( effect_onfire, rng( 1_turns, 4_turns ), bp_hit ); } } else if (proj.proj_effects.count("IGNITE")) { if (made_of( material_id( "veggy" ) ) || made_of( material_id( "cotton" ) ) || made_of( material_id( "wool" ) ) || made_of( material_id( "paper" ) ) || made_of( material_id( "wood" ) ) ) { add_effect( effect_onfire, 6_turns, bp_hit ); } else if (made_of( material_id( "flesh" ) ) || made_of( material_id( "iflesh" ) ) ) { add_effect( effect_onfire, 10_turns, bp_hit ); } } if( bp_hit == bp_head && proj_effects.count( "BLINDS_EYES" ) ) { // TODO: Change this to require bp_eyes add_env_effect( effect_blind, bp_eyes, 5, rng( 3_turns, 10_turns ) ); } if( proj_effects.count( "APPLY_SAP" ) ) { add_effect( effect_sap, 1_turns * dealt_dam.total_damage() ); } int stun_strength = 0; if (proj.proj_effects.count("BEANBAG")) { stun_strength = 4; } if (proj.proj_effects.count("LARGE_BEANBAG")) { stun_strength = 16; } if( stun_strength > 0 ) { switch( get_size() ) { case MS_TINY: stun_strength *= 4; break; case MS_SMALL: stun_strength *= 2; break; case MS_MEDIUM: default: break; case MS_LARGE: stun_strength /= 2; break; case MS_HUGE: stun_strength /= 4; break; } add_effect( effect_stunned, 1_turns * rng( stun_strength / 2, stun_strength ) ); } if(u_see_this) { if( damage_mult == 0 ) { if( source != nullptr ) { add_msg( source->is_player() ? _("You miss!") : _("The shot misses!") ); } } else if( dealt_dam.total_damage() == 0 ) { //~ 1$ - monster name, 2$ - character's bodypart or monster's skin/armor add_msg( _("The shot reflects off %1$s %2$s!"), disp_name(true).c_str(), is_monster() ? skin_name().c_str() : body_part_name_accusative(bp_hit).c_str() ); } else if( is_player() ) { //monster hits player ranged //~ Hit message. 1$s is bodypart name in accusative. 2$d is damage value. add_msg_if_player(m_bad, _( "You were hit in the %1$s for %2$d damage." ), body_part_name_accusative(bp_hit).c_str(), dealt_dam.total_damage()); } else if( source != nullptr ) { if( source->is_player() ) { //player hits monster ranged SCT.add(posx(), posy(), direction_from(0, 0, posx() - source->posx(), posy() - source->posy()), get_hp_bar(dealt_dam.total_damage(), get_hp_max(), true).first, m_good, message, gmtSCTcolor); if (get_hp() > 0) { SCT.add(posx(), posy(), direction_from(0, 0, posx() - source->posx(), posy() - source->posy()), get_hp_bar(get_hp(), get_hp_max(), true).first, m_good, //~ "hit points", used in scrolling combat text _("hp"), m_neutral, "hp"); } else { SCT.removeCreatureHP(); } add_msg(m_good, _("You hit %s for %d damage."), disp_name().c_str(), dealt_dam.total_damage()); } else if( u_see_this ) { //~ 1$ - shooter, 2$ - target add_msg(_("%1$s shoots %2$s."), source->disp_name().c_str(), disp_name().c_str()); } } } check_dead_state(); attack.hit_critter = this; attack.missed_by = goodhit; }
//--------- Begin of function FirmCamp::disp_camp_info ---------// // void FirmFort::disp_camp_info(int dispY1, int refreshFlag) { FirmCamp::disp_camp_info(dispY1, refreshFlag); // ----- display train button -------// int x2 = INFO_X1 +13; int y2 = INFO_Y1 +281; if (!is_monster()) button_train.create( INFO_X1+13, INFO_Y1+281, 'A', "TRAIN" ); else button_train.create( INFO_X1+13, INFO_Y1+281, 'A', "F_TRAIN" ); // scan any available population to train // ##### begin Gilbert 23/12 #######// if( (button_train.visible_flag = is_own()) ) { button_train.enable_flag = can_recruit(active_link_town_recno); button_train.paint(); } // ##### end Gilbert 23/12 #######// // ------- display tower count -----// button_tower_count.create( INFO_X1+13+3*BUTTON_DISTANCE+6, INFO_Y1+235+6, INFO_X1+13+3*BUTTON_DISTANCE+6+TOWER_COUNT_BUTTON_WIDTH-1, INFO_Y1+235+6+TOWER_COUNT_BUTTON_HEIGHT-1, disp_tower_count, ButtonCustomPara( NULL, 0 ) ); //#ifdef DEBUG // BUGHERE : ARM_TOWERS is longer than 8 characters // button_tower_count.set_help_code("ARM_TOWERS"); button_tower_count.set_help_code("ARM_TOWE"); //#endif button_tower_count.enable_flag = is_own(); button_tower_count.custom_para = ButtonCustomPara( NULL, target_archer_count ); button_tower_count.paint(); // ------- display towers ----------// err_when( !image_spict.read_all ); // must read_all char *towerFull = image_spict.read("TOWER-F"); char *towerEmpty = image_spict.read("TOWER-E"); char *towerBuilding = image_spict.read("TOWER-D"); int towerHeight = ((Bitmap *)towerFull)->get_height(); err_when( ((Bitmap *)towerEmpty)->get_height() != towerHeight ); err_when( ((Bitmap *)towerBuilding)->get_height() != towerHeight ); int towerWidth = ((Bitmap *)towerFull)->get_width(); // static int towerXTable[MAX_FORT_ARCHER] = { 180, 202, 191, 180, 202 }; // static int towerYTable[MAX_FORT_ARCHER] = { 280, 280, 292, 304, 304 }; static int towerXTable[MAX_FORT_ARCHER] = { 180, 202, 191, 180, 202 }; static int towerYTable[MAX_FORT_ARCHER] = { 304, 304, 292, 280, 280 }; for( int i = 0; i < MAX_FORT_ARCHER; ++i ) { int towerX = INFO_X1 + towerXTable[i]; int towerY = INFO_Y1 + towerYTable[i]; if( i < current_archer_count ) { // display full tower vga.active_buf->put_bitmap( towerX, towerY, towerFull ); } else if( i == current_archer_count ) { // display building tower vga.active_buf->put_bitmap( towerX, towerY, towerEmpty ); // display portion of towerFull at bottom int subTowerHeight = train_archer_progress * towerHeight / MAX_TRAIN_ARCHER_PROGRESS; if( subTowerHeight > 0 ) { vga.active_buf->put_bitmap_area( towerX, towerY, towerBuilding, 0, towerHeight-subTowerHeight, towerWidth-1, towerHeight-1 ); } } else { // display disabled tower vga.active_buf->put_bitmap( towerX, towerY, towerEmpty ); } } help.set_help( INFO_X1+176, INFO_Y1+278, INFO_X1+176+39, INFO_Y1+278+48, "TOWERS" ); }
//--------- Begin of function Unit::betray ---------// // // If this unit is a spy, this function betray() will be // called by Unit::spy_change_nation() or Firm::capture_firm(). // // If this is not a spy, this function will only be called // by think_betray() and other nation deinit functions. // int Unit::betray(int newNationRecno) { //----- if this is a spy, call spy_change_nation -----// if( spy_recno && spy_array[spy_recno]->cloaked_nation_recno != newNationRecno ) // cloaked_nation_recno == newNationRecno if betray() is called by spy_change_nation() already { spy_change_nation(newNationRecno, COMMAND_AUTO); return 1; } //-------------------------------// err_when( newNationRecno && nation_array[newNationRecno]->is_human() && // monsters in firms should not betray to humans is_monster() && unit_mode == UNIT_MODE_OVERSEE ); int unitRecno = sprite_recno; err_when( unit_array.is_truly_deleted(unitRecno) ); err_when( rank_id == RANK_KING ); if( nation_recno == newNationRecno ) return 0; if( unit_mode == UNIT_MODE_CONSTRUCT_FIRM || // don't change nation when the unit is constructing a firm unit_mode == UNIT_MODE_CONSTRUCT_TOWN || unit_mode == UNIT_MODE_ON_SHIP ) // don't change nation when the unit is constructing a firm { return 0; } //--- special case: units in Monster Fortress cannot change nation ---// if( unit_mode == UNIT_MODE_OVERSEE && firm_array[unit_mode_para]->firm_id == FIRM_FORTRESS ) { return 0; } //---------- add news -----------// if( nation_recno == nation_array.player_recno || newNationRecno == nation_array.player_recno ) { //--- if this is a spy, don't display news message for betrayal as it is already displayed in Unit::spy_change_nation() ---// if( !spy_recno ) news_array.unit_betray(sprite_recno, newNationRecno); } //------ change nation now ------// err_when( unit_array.is_truly_deleted(unitRecno) ); change_nation(newNationRecno); err_when( unit_array.is_truly_deleted(unitRecno) ); //-------- set the loyalty of the unit -------// if( nation_recno ) { Nation* nationPtr = nation_array[nation_recno]; loyalty = UNIT_BETRAY_LOYALTY + 10 + m.random(20); if( nationPtr->reputation > 0 ) change_loyalty( (int) nationPtr->reputation ); if( race_res.is_same_race( nationPtr->race_id, race_id ) ) change_loyalty( 30 ); err_when( loyalty < 0 || loyalty > 100 ); update_loyalty(); // update target loyalty } else //------ if change to independent rebel -------// { loyalty = 0; // no loyalty needed } //--- if this unit is a general, change nation for the units he commands ---// if( rank_id==RANK_GENERAL ) { err_when( !team_info ); for( int i=0 ; i<team_info->member_count ; i++ ) { int memberUnitRecno = team_info->member_unit_array[i]; if( memberUnitRecno == unitRecno ) // this is the unit itself continue; Unit* unitPtr = unit_array[memberUnitRecno]; if( !unitPtr->is_visible() ) continue; if( unitPtr->spy_recno ) // if the unit is a spy unitPtr->spy_change_nation(newNationRecno, COMMAND_AUTO); else unitPtr->change_nation(newNationRecno); } } err_when( unit_array.is_truly_deleted(unitRecno) ); //------ go to meet the new master -------// if( is_visible() && nation_recno ) { if( !spy_recno || spy_array[spy_recno]->notify_cloaked_nation_flag ) { if( is_civilian() ) ai_move_to_nearby_town(); else ai_move_to_nearby_firm(FIRM_CAMP, FIRM_FORT); } } err_when( unit_array.is_truly_deleted(unitRecno) ); return 1; }
//--------- Begin of function FirmCamp::disp_camp_info ---------// // void FirmCamp::disp_camp_info(int dispY1, int refreshFlag) { if( is_own() ) { int x1 = INFO_X1 +13; int y1 = INFO_Y1 +235; int x2 = INFO_X1 +13; int y2 = INFO_Y1 +281; if( refreshFlag==INFO_REPAINT ) { // ##### begin Gilbert 31/12 #######// // button_patrol.create( INFO_X1+13, INFO_Y1+235, 'A', "PATROL" ); // button_reward.create( INFO_X1+13+BUTTON_DISTANCE, INFO_Y1+235, 'A', "REWARDCB" ); // button_defense.create( INFO_X1+13+2*BUTTON_DISTANCE, INFO_Y1+235, 'A', defense_flag ? "DEFENSE1" : "DEFENSE0" ); if (!is_monster()) button_patrol.create( INFO_X1+13+BUTTON_DISTANCE, INFO_Y1+281, 'A', "PATROL" ); else button_patrol.create( INFO_X1+13+BUTTON_DISTANCE, INFO_Y1+281, 'A', "F_PATROL" ); if (!is_monster()) button_reward.create( INFO_X1+13, INFO_Y1+235, 'A', "REWARD" ); else button_reward.create( INFO_X1+13, INFO_Y1+235, 'A', "F_REWARD" ); if (!is_monster()) button_defense.create( INFO_X1+13+2*BUTTON_DISTANCE, INFO_Y1+281, 'A', defense_flag ? "DEFENSE1" : "DEFENSE0" ); else button_defense.create( INFO_X1+13+2*BUTTON_DISTANCE, INFO_Y1+281, 'A', defense_flag ? "F_DEFEN1" : "F_DEFEN0" ); if (!is_monster()) button_promote.create( INFO_X1+13+2*BUTTON_DISTANCE , INFO_Y1+235, 'A', "PROMOTE" ); else button_promote.create( INFO_X1+13+2*BUTTON_DISTANCE , INFO_Y1+235, 'A', "F_PROMOT" ); // ##### end Gilbert 31/12 #######// } if( overseer_recno ) { button_patrol.enable_flag = 1; } else { for( int i = 0; i < soldier_count && soldier_array[i].is_under_training(); ++i ); button_patrol.enable_flag = i < soldier_count; } String str; switch(patrol_state) { case PATROL_ALL: // str = "Sortie All"; str = ""; break; case PATROL_NO_GENERAL: str = "Sortie No Leader"; break; case PATROL_NO_INJURED_SOILDER: str = "Sortie No Injured"; break; default: break; } button_patrol.paint(); // vga.active_buf->bar_alpha( button_patrol.x1, button_patrol.y1+15, button_patrol.x1+BUTTON_ACTION_WIDTH-1, button_patrol.y1+BUTTON_ACTION_HEIGHT-16, 1, 0 ); font_whbl.center_put_paragraph( button_patrol.x1, button_patrol.y1, button_patrol.x1+BUTTON_ACTION_WIDTH-1, button_patrol.y1+BUTTON_ACTION_HEIGHT-1, str ); // ###### begin Gilbert 15/4 ########// if( nation_array[nation_recno]->cash >= REWARD_COST && ( (overseer_recno && unit_array[overseer_recno]->rank_id != RANK_KING && unit_res[unit_array[overseer_recno]->unit_id]->class_info.has_loyalty) || (selected_soldier_id && selected_soldier_id <= soldier_count && unit_res[soldier_array[selected_soldier_id-1].unit_id]->class_info.has_loyalty)) ) button_reward.enable_flag = 1; // call paint // ###### end Gilbert 15/4 ########// else button_reward.enable_flag = 0; // call paint button_reward.paint(); if (!is_monster()) button_defense.update_bitmap( defense_flag ? "DEFENSE1" : "DEFENSE0" ); // call paint else button_defense.update_bitmap( defense_flag ? "F_DEFEN1" : "F_DEFEN0" ); if( (button_promote.visible_flag = !overseer_recno) ) { button_promote.enable_flag = 0; if( selected_soldier_id > 0 && selected_soldier_id <= soldier_count ) { Soldier *soldierPtr = soldier_array + selected_soldier_id - 1; // ##### begin Gilbert 24/3 ######// err_when( soldierPtr->unit_id == UNIT_WAGON ); if( soldierPtr->race_id != 0 && soldierPtr->rank_id == RANK_SOLDIER && !soldierPtr->is_under_training() && soldierPtr->skill_level() > 0 ) // ##### end Gilbert 24/3 ######// { button_promote.enable_flag = 1; } } button_promote.paint(); } } disp_spy_button( INFO_X1+13+BUTTON_DISTANCE, INFO_Y1+281, refreshFlag); }
//--------- Begin of function Unit::init ---------// // // <int> unitId - the id. of the unit // <int> nationRecno - the recno of nation // [int] rankId - rank id. of the unit (none for non-human unit) // [int] unitLoyalty - loyalty of the unit (none for non-human unit) // [int] startXLoc, startYLoc - the starting location of the unit // (if startXLoc < 0, this is a unit for hire, and is not a unit of the game yet. init_sprite() won't be called for this unit) // (default: -1, -1) // // Note: sprite_recno must be initialized first before calling Unit::init() // void Unit::init(int unitId, int nationRecno, int rankId, int unitLoyalty, int startXLoc, int startYLoc) { //------------ set basic vars -------------// nation_recno = (char) nationRecno; rank_id = rankId; // rank_id must be initialized before init_unit_id() as init_unit_id() may overwrite it if( rank_id == RANK_GENERAL || rank_id == RANK_KING ) { err_when( team_info ); team_info = (TeamInfo*) mem_add( sizeof(TeamInfo) ); memset( team_info, 0, sizeof(TeamInfo) ); } init_unit_id(unitId); race_id = (char) unit_res[unit_id]->race_id; //------- init unit name ---------// if( is_human() && unit_id != UNIT_WAGON ) { name_id = race_res[race_id]->get_new_name_id(); } else if( is_monster() ) { name_id = monster_res.get_new_name_id(); } else //---- init non-human unit series no. ----// { if( nation_recno ) name_id = ++nation_array[nation_recno]->last_unit_name_id_array[unit_id-1]; else name_id = 0; } // ###### begin Gilbert 23/2 ######// unique_id = misc.rand_long(); // ###### end Gilbert 23/2 ######// //---------- init other vars ----------// err_when( unitLoyalty < 0 || unitLoyalty > 100 ); loyalty = unitLoyalty; // ##### begin Gilbert 29/5 ########// if( is_die_after_attack() ) // behavior_mode = UNIT_STAND_GROUND; // bee die after attack, so don't waste his life behavior_mode = UNIT_DEFENSIVE; // bee die after attack, so don't waste his life else behavior_mode = UNIT_AGGRESSIVE; // the default mode is aggressive // ##### end Gilbert 29/5 ########// //--------- init skill, and skill potential ---------// skill.init(unit_id, 100); set_combat_level(-1); hit_points = (float) max_hit_points(); //------ initialize the base Sprite class -------// if( startXLoc >= 0 ) init_sprite( startXLoc, startYLoc ); else cur_x = -1; //-------------- update loyalty -------------// update_loyalty(); //--------------- init AI info -------------// init_ai(); //----------- init derived class ----------// init_derived(); set_combat_level(-1); }
//--------- Begin of function Unit::deinit ---------// // void Unit::deinit() { //---------- free up team_info ----------// if( team_info ) { mem_del(team_info); team_info = NULL; } //---------------------------------------// // ####### begin Gilbert 22/3 ########// if( sys.quick_exit_flag() ) { if( game.is_campaign_mode() ) { // if in campaign mode, free name before exit if( name_id ) { if( is_human() && unit_id != UNIT_WAGON ) { if( name_id ) race_res[race_id]->free_name_id( name_id ); } else if( is_monster() ) { if( name_id ) monster_res.free_name_id( name_id ); } else //---- init non-human unit series no. ----// { } name_id = 0; } } return; } // ####### end Gilbert 22/3 ########// //---------------------------------------// err_when( unit_array.is_truly_deleted(sprite_recno) ); if( !unit_id ) return; // ######### begin Gilbert 23/2 #######// // -------- update win/lose condition or die -------// if( hit_points <= 0.0f || cur_action == SPRITE_DIE ) { game.update_condition_on_killed( unique_id ); } // ######### end Gilbert 23/2 #######// //--------- drop item -----------// if( !sys.signal_exit_flag && item.id ) { drop_item(COMMAND_AUTO); } //-------- if this is a king --------// if( !sys.signal_exit_flag && nation_recno ) { if( rank_id == RANK_KING ) // check nation_recno because monster kings will die also. { king_die(); err_when( unit_array.is_truly_deleted(sprite_recno) ); } else if( rank_id == RANK_GENERAL ) { general_die(); err_when( unit_array.is_truly_deleted(sprite_recno) ); } } // ####### begin Gilbert 12/3 #######// // -------- free name id after general_die, which reads name_id ---------// if( name_id ) { if( is_human() && unit_id != UNIT_WAGON ) { if( name_id ) race_res[race_id]->free_name_id( name_id ); } else if( is_monster() ) { if( name_id ) monster_res.free_name_id( name_id ); } else //---- init non-human unit series no. ----// { } name_id = 0; } // ####### end Gilbert 12/3 #######// //---- if this is a general, deinit its link with its soldiers ----// // // We do not use team_info because monsters and rebels also use // leader_unit_recno and they do not use keep the member info // in team_info. // //-----------------------------------------------------------------// if( rank_id == RANK_GENERAL || rank_id == RANK_KING ) { for( int i=unit_array.size() ; i>0 ; i-- ) { if( unit_array.is_deleted(i) ) continue; if( unit_array[i]->leader_unit_recno == sprite_recno ) unit_array[i]->leader_unit_recno = 0; } } //----- if this is a unit on a ship ------// if( unit_mode == UNIT_MODE_ON_SHIP ) { err_here(); /* if( !unit_array.is_deleted(unit_mode_para) ) // the ship may have been destroyed at the same time. Actually when the ship is destroyed, all units onboard are killed and this function is called. { Unit* unitPtr = unit_array[unit_mode_para]; err_when( unit_res[unitPtr->unit_id]->unit_class != UNIT_CLASS_SHIP ); ((UnitMarine*)unitPtr)->del_unit(sprite_recno); } */ } //----- if this is a ship in the harbor -----// else if( unit_mode == UNIT_MODE_IN_HARBOR ) { err_here(); /* if( !firm_array.is_deleted(unit_mode_para) ) // the ship may have been destroyed at the same time. Actually when the ship is destroyed, all firms onboard are killed and this function is called. { Firm* firmPtr = firm_array[unit_mode_para]; err_when( firmPtr->firm_id != FIRM_HARBOR ); ((FirmHarbor*)firmPtr)->del_hosted_ship(sprite_recno); } */ } //----- if this unit is a constructor in a firm -------// else if( unit_mode == UNIT_MODE_CONSTRUCT_FIRM ) { err_when( firm_array[unit_mode_para]->builder_recno != sprite_recno ); firm_array[unit_mode_para]->builder_recno = 0; } //----- if this unit is a constructor in a town -------// else if( unit_mode == UNIT_MODE_CONSTRUCT_TOWN ) { err_when( town_array[unit_mode_para]->builder_recno != sprite_recno ); town_array[unit_mode_para]->builder_recno = 0; } //-------- if this is a spy ---------// if( spy_recno ) { spy_array.del_spy( spy_recno ); spy_recno = 0; } //---------- reset command ----------// if( power.command_unit_recno == sprite_recno ) power.reset_command(); //-----------------------------------// deinit_unit_id(); //----- if cur_x == -1, the unit has not yet been hired -----// if( cur_x >= 0 ) deinit_sprite(); // ##### patch begin Gilbert 6/10 ######// else if( selected_flag ) // caravan may be deinit_sprite(1) and keep selected, now unselect { int curSelected = unit_array.selected_recno == sprite_recno; // if it is currently selected unit, reset selected_recno deselect(); if( curSelected && !sys.signal_exit_flag ) info.disp(); } // ##### patch end Gilbert 6/10 ######// //--------------- deinit AI info -------------// deinit_ai(); //-------------- reset unit_id ---------------// unit_id = 0; }
// -------- begin of function FirmResearch::disp_firm_info --------// // void FirmResearch::disp_firm_info(int dispY1, int refreshFlag) { String str; int techId = nation_array[nation_recno]->research_tech_id; // ###### begin Gilbert 5/10 ######// //---------------- paint the panel --------------// // techId =1; if( !techId ) { // str = "No Technology is"; // font_snds.center_put( INFO_X1+7, INFO_Y1+31, INFO_X2, INFO_Y1+48, str ); // str = "currently being"; // font_snds.center_put( INFO_X1+7, INFO_Y1+60, INFO_X2, INFO_Y1+77, str ); // str = "researched."; // font_snds.center_put( INFO_X1+7, INFO_Y1+89, INFO_X2, INFO_Y1+106, str ); font_snds.center_put_paragraph( INFO_X1+45, INFO_Y1+31, INFO_X2-40, INFO_Y1+106, text_firm.str_no_research(), 16, 0, 0 ); } else { //-------- display the icon of the researching item ---------// int x = INFO_X1; int y = INFO_Y1; TechInfo* techInfo = tech_res[techId]; //----------- display text ------------// // str = "Research Progress"; font_snds.center_put( INFO_X1+7, INFO_Y1+11, INFO_X2, INFO_Y1+28, text_firm.str_research_progress() ); // <tech> <version> str = techInfo->tech_des(); int researchVersion = techInfo->get_nation_tech_level(nation_recno)+1; // research the next non-researched version if( researchVersion > 1 ) { str += " "; str += m.roman_number(researchVersion); } font_snds.center_put( INFO_X1+7, INFO_Y1+28, INFO_X2, INFO_Y1+45, str ); // str = "Completion Percent"; font_snds.center_put( INFO_X1+7, INFO_Y1+97, INFO_X2, INFO_Y1+114, text_firm.str_completion_percent() ); // <completion> % int researchProgress = (int) nation_array[nation_recno]->research_progress(); str = (int) researchProgress; str += " %"; font_snds.center_put( INFO_X1+7, INFO_Y1+97+18, INFO_X2, INFO_Y1+114+18, str ); short* hitPointBitmap =NULL; int ratio = researchProgress * 40 / 100; int size = researchProgress * 76 / 100; //106 x 35 --- 15 to 90 ie. 0 to 40 // hitPointBitmap = (short *)mem_add( BitmapW::size(15 +size, 35) ); // if (ratio <11) // vga.active_buf->put_bitmap_trans( INFO_X1 +62, INFO_Y1 +59, image_spict.read("MTR_10")); // else // if (ratio <40) // vga.active_buf->put_bitmap_trans( INFO_X1 +62, INFO_Y1 +59, image_spict.read("MTR_39")); // else // vga.active_buf->put_bitmap_trans( INFO_X1 +62, INFO_Y1 +59, image_spict.read("MTR_40")); // vga.active_buf->read_bitmapW( INFO_X1 +62, INFO_Y1 +59, INFO_X1 +75 +size, INFO_Y1 +90, hitPointBitmap ); // vga.active_buf->put_bitmap_trans( INFO_X1 +62, INFO_Y1 +59, image_spict.read("MTR_00")); // vga.active_buf->put_bitmapW( INFO_X1 +62, INFO_Y1 +59, hitPointBitmap ); // mem_del( hitPointBitmap ); // ----- put empty bar ------// vga.active_buf->put_bitmap_trans( INFO_X1 +62, INFO_Y1 +59, image_spict.read("MTR_00")); // ----- put bar content -----// if( size > 0 ) { char *barBitmap; if (ratio <11) barBitmap = image_spict.read("MTR_10"); else if (ratio <40) barBitmap = image_spict.read("MTR_39"); else barBitmap = image_spict.read("MTR_40"); vga.active_buf->put_bitmap_area_trans( INFO_X1+62, INFO_Y1+59, barBitmap, 0, 0, 13+size, ((Bitmap *)barBitmap)->get_height()-1 ); } } // int x1 = INFO_X1 +13; // int y1 = INFO_Y1 +235; // int x2 = INFO_X1 +13; // int y2 = INFO_Y1 +281; if( is_own() ) { if (!is_monster()) button_select_research.create( INFO_X1 +13, INFO_Y1 +281, 'A', "RESEARCH" ); else button_select_research.create( INFO_X1 +13, INFO_Y1 +281, 'A', "F_RESE" ); button_select_research.paint(); } // ###### end Gilbert 5/10 ######// }