Пример #1
0
	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;
	}
Пример #2
0
//------- 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);
}
Пример #3
0
//----- 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;
}
Пример #4
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;
}
Пример #5
0
//--------- 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" );
}
Пример #6
0
//--------- 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;
}
Пример #7
0
//--------- 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);
}
Пример #8
0
//--------- 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);
}
Пример #9
0
//--------- 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;
}
Пример #10
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 ######//
}