Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Game difficulty number of followers should effect outcome of fights #202

6 changes: 5 additions & 1 deletion main/midnight/src/tme/baseinc/info.h
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ inline chilli::lib::archive& operator>>( chilli::lib::archive& ar, mxunit& unit
virtual bool CheckRecruitChar ( mxcharacter* pChar ) const ;
virtual bool Recruited ( mxcharacter* recruiter );
virtual void SetRecruitmentTime( mxcharacter* recruiter );
virtual void LostFight ( void );
virtual void LostFight ( s32 hint = 0 );
virtual void LostBattle ( bool canFlee );
virtual void Displace ( void );
virtual void DecreaseEnergy ( s32 amount );
Expand All @@ -1011,6 +1011,10 @@ inline chilli::lib::archive& operator>>( chilli::lib::archive& ar, mxunit& unit
virtual mxthing_t LocationThing() const ;
virtual void RefreshLocationBasedVariables ( const mxlocinfo* info ) ;
virtual bool CanWalkForward ( void );
virtual bool ShouldLoseHorse(s32 hint = 0) const;
virtual bool ShouldDieInFight() const;
virtual bool ShouldHaveOneToOneWithNasty() const;
virtual void Dismount();

virtual bool AddFollower ( mxcharacter* c );
virtual bool RemoveFollower ( mxcharacter* c );
Expand Down
8 changes: 7 additions & 1 deletion main/midnight/src/tme/baseinc/mxengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
#define EOS(x) x+c_strlen(x)



namespace tme {


FORWARD_REFERENCE(mxentityfactory);

//using namespace tme::collections;

DECLARE_ENUM(arguments) {
Expand Down Expand Up @@ -119,6 +122,8 @@ namespace tme {
return static_cast<mxcharacter*>(EntityByName(symbol, IDT_CHARACTER));
}

mxentity* CreateEntity ( id_type_t type );


public:
mxmap* gamemap;
Expand All @@ -128,6 +133,7 @@ namespace tme {
mxbattle* battle;
mxgameover* gameover;
mxscenario* scenario;
mxentityfactory* entityfactory;

c_character objCharacters;
c_regiment objRegiments;
Expand Down
82 changes: 60 additions & 22 deletions main/midnight/src/tme/scenario/item_character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,17 +386,31 @@ namespace tme {
return false ;
}

void mxcharacter::LostFight ( void )
bool mxcharacter::ShouldLoseHorse(s32 hint) const
{
return mxrandom() & 1;
}

bool mxcharacter::ShouldDieInFight() const
{
auto temp = (energy/2) - 64 + reckless;
return mxrandom(255) >= temp;
}

void mxcharacter::Dismount()
{
flags.Reset ( cf_riding );
}

void mxcharacter::LostFight ( s32 hint )
{
int temp;
if ( !IsDead() ) {
if ( IsRiding() ) {
if (mxrandom() & 1)
flags.Reset ( cf_riding );
if (ShouldLoseHorse())
Dismount();
}

temp = (energy/2) - 64 + reckless;
if (mxrandom(255) >= temp) {
if (ShouldDieInFight()) {
Cmd_Dead();
}
}
Expand Down Expand Up @@ -949,50 +963,74 @@ namespace tme {
return result;
}

bool mxcharacter::ShouldHaveOneToOneWithNasty() const
{
// allow game difficulty to have an effect
// on the grouping
if ( mx->Difficulty() == DF_EASY && followers>= 2 ) {
return false;
}
if ( mx->Difficulty() == DF_MEDIUM || mx->Difficulty() == DF_NORMAL ) {
if ( followers >= 3 )
return false;
}
return true;
}

mxobject* mxcharacter::Cmd_Fight ( void )
{
bool objectautokill = false ;
int friends_armies=0;
bool needfight = true ;
bool killedwithobject = false;

SetLastCommand ( CMD_FIGHT, IDT_NONE );

std::unique_ptr<mxlocinfo> info ( GetLocInfo() );

auto fightobject = mx->ObjectById(info->fightthing) ;
friends_armies = info->friends.armies ;

// are we allowed to fight
if ( !info->flags.Is(lif_fight) )
fightobject = nullptr ;

return nullptr ;
// is there anything to fight
auto fightobject = mx->ObjectById(info->fightthing) ;
if ( fightobject == nullptr )
return nullptr ;

SetLastCommand ( CMD_FIGHT,SafeIdt(fightobject)) ;

auto oinfo = Carrying();
objectautokill = oinfo ? oinfo->CanDestroy(fightobject) : false ;

// if there is any friends here
// then we win by default
if ( friends_armies == 0 && !objectautokill && !sv_cheat_always_win_fight ) {
if (info->friends.armies)
needfight = false;

auto oinfo = Carrying();
if (oinfo != nullptr && oinfo->CanDestroy(fightobject)) {
needfight = false;
killedwithobject = true;
}

if ( sv_cheat_always_win_fight )
needfight = false;

if ( !ShouldHaveOneToOneWithNasty() )
needfight = false;

if ( needfight ) {

LostFight();

if ( IsDead() ) {
killedbyobject = fightobject ;
return fightobject;
}

}

// we have killed the enemy
//
// we have killed the nasty
mx->text->oinfo = fightobject;

// describe that
u32 message = objectautokill ? oinfo->usedescription : SS_FIGHT ;
// describe how
u32 message = killedwithobject
? oinfo->usedescription
: SS_FIGHT ;

mx->SetLastActionMsg(mx->text->CookedSystemString(message, this));

Expand Down
14 changes: 2 additions & 12 deletions main/midnight/src/tme/scenarios/citadel/citadel_scenario.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ MXRESULT citadel_x::Register ( mxengine* midnightx )
mx->text = new mxtext;
mx->night = new mxnight;
mx->battle = new mxbattle;
mx->entityfactory = new mxentityfactory;
mx->scenario = (mxscenario*)citadel_scenario;

// set initial feature flags
Expand All @@ -115,25 +116,14 @@ MXRESULT citadel_x::UnRegister ( mxengine* midnightx )
SAFEDELETE ( mx->text ) ;
SAFEDELETE ( mx->night ) ;
SAFEDELETE ( mx->battle ) ;
SAFEDELETE ( mx->entityfactory );

// mx will delete the scenario, so just lose our
// reference to it
citadel_scenario = NULL ;
return MX_OK ;
}



mxentity* citadel_x::CreateEntity ( id_type_t type )
{
// switch ( type ) {
// case IDT_STRONGHOLD:
// return (mxentity*) new lom_stronghold ;
// }

return mxscenario::CreateEntity ( type );
}

} // SCENARIOS

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ namespace tme {
virtual scenarioinfo_t* GetInfoBlock() const;
virtual MXRESULT Register ( mxengine* midnightx );
virtual MXRESULT UnRegister ( mxengine* midnightx );
virtual mxentity* CreateEntity ( id_type_t type );

};

}
Expand Down
76 changes: 61 additions & 15 deletions main/midnight/src/tme/scenarios/ddr/ddr_character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ namespace tme {

return info;
}

mxobject* ddr_character::Cmd_Fight()
{
SetLastCommand ( CMD_FIGHT, IDT_NONE );
Expand All @@ -166,20 +166,21 @@ namespace tme {

if ( ! sv_cheat_always_win_fight )
{
u32 r = mxrandom(255) & 15 ;
s32 loses = (r/2)*5;
u32 hp = fightobject->FightHP();
s32 loses = fightobject->KillRate(hp);

// soldiers -= loses ;
warriors.Loses(loses);
riders.Loses(loses);

static u8 critter_success[] = { 0, 9, 8, 10, 11 };

if ( r > critter_success[fightobject->Id()] ) {
static_cast<ddr_battle*>(mx->battle)->loseFight(this,r);
if ( IsDead() ) {
killedbyobject = fightobject;
return fightobject;

auto needfight = ShouldHaveOneToOneWithNasty();

if ( needfight ) {
if ( hp > fightobject->FightSuccess() ) {
LostFight(hp);
if ( IsDead() ) {
killedbyobject = fightobject;
return fightobject;
}
}
}
}
Expand All @@ -198,12 +199,57 @@ namespace tme {

}

void ddr_character::LostFight ( void )
bool ddr_character::ShouldLoseHorse(s32 hint) const
{
// stubber out
return (hint&3) == 1;
}

bool ddr_character::HasBattleObject() const
{
auto object = static_cast<ddr_object*>(Carrying());
return object != nullptr && object->power == OP_BATTLE ;
}

bool ddr_character::IsProtected() const
{
auto object = static_cast<ddr_object*>(Carrying());
return object != nullptr && object->power == OP_PROTECTION;
}

bool ddr_character::ShouldDieInFight() const
{
u32 r = mxrandom(255);
if ( (r&1) == 0 )
return false;

if ( reckless > r )
return false;

if ( HasBattleObject()) {
if ( mxrandom(255) >= 80 )
return false;
}

return true;
}

void ddr_character::LostFight ( s32 hint )
{
if ( IsProtected() ) {
return;
}


if ( ShouldLoseHorse(hint) ) {
Flags().Reset(cf_riding);
}

if ( !ShouldDieInFight() ) {
return;
}

Cmd_Dead();
}

void ddr_character::DecreaseEnergy ( s32 amount )
{
mxrace* rinfo = mx->RaceById(Race());
Expand Down
25 changes: 25 additions & 0 deletions main/midnight/src/tme/scenarios/ddr/ddr_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,31 @@ namespace tme {
return FALSE;
}

u32 ddr_object::FightHP() const
{
return mxrandom(255) & 15;
}

u32 ddr_object::FightSuccess() const
{
auto thing = (mxthing_t)Id();

switch (thing) {
case OB_WOLVES: return 9;
case OB_DRAGONS: return 8;
case OB_ICETROLLS: return 10;
case OB_SKULKRIN: return 11;
default:
return 0;
}
}

u32 ddr_object::KillRate( u32 hp ) const
{
return (hp/2) * 5;
}


MXRESULT ddr_object::FillExportData ( info_t* data )
{
using export_t = tme::scenarios::ddr::exports::object_t;
Expand Down
Loading