What does the "disarm" attribute on swords do?
There is the DISARM_MODE toggle at the bottom of PROGRAM\InternalSettings.h that triggers this section in PROGRAM\Loc_ai\LAi_events.c:
Code:
// CCC and PB: New attribute to weapons to allow for disarming opponents
bool tbool = CheckAttribute(enemy, "equip.blade");
if(tbool) tbool = GetCharacterEquipByGroup(enemy,BLADE_ITEM_TYPE) != "bladeX4";
if( DISARM_MODE && CheckAttribute(weapon, "disarm" ) && LAi_IsFightMode(enemy) && !CheckAttribute(enemy, "nodisarm" ) && tbool)
{
int disarmbonus = 0;
if(CheckAttribute(attack,"perks.list.SwordplayProfessional")) {disarmbonus = 20;}
// if attacker has professional fencing skill, increase disarm chance with 20%
int disarmpenalty = 0;
if(CheckAttribute(enemy,"perks.list.SwordplayProfessional")) {disarmpenalty = 10;}
// if attacked victim has professional fencing skill, decrease disarm chance with 10%
if(sti(rand(100)+enemy.skill.Fencing) < sti(weapon.disarm)+sti(attack.skill.Fencing) + disarmbonus - disarmpenalty)
{
LAi_CharacterPlaySound(enemy,"OBJECTS\duel\sword_fallen.wav");
string enemy_blade = GetCharacterEquipByGroup(enemy,BLADE_ITEM_TYPE);
RemoveCharacterEquip(enemy, BLADE_ITEM_TYPE );
GiveItem2Character(attack, enemy_blade);
if ( enemy.chr_ai.group != LAI_GROUP_PLAYER && !bAbordageStarted )
// no disarming opponents during boarding
{
LAi_SetCitizenTypeNoGroup(enemy);
Log_SetStringToLog(TranslateString("","Opponent disarmed !"));
}
else
{
TakeItemFromCharacter(enemy, enemy_blade);
if ( sti(enemy.index) != GetMainCharacterIndex() && !bAbordageStarted ) // if NOT player
// officers safe from being disarmed boarding; player NOT safe from being disarmed during boarding
{
RemoveCharacterEquip(attack, BLADE_ITEM_TYPE ); // makes enemy use your blade against your officer
EquipCharacterByItem(attack, enemy_blade); // and enables you to get it back by killing him/her
Log_SetStringToLog(TranslateString("","One of your officers was disarmed!"));
LAi_tmpl_afraid_SetAfraidCharacter(enemy, attack, true); // makes officer flee
LAi_SetAfraidDead(enemy);
}
else
{
RemoveCharacterEquip(attack, BLADE_ITEM_TYPE ); // makes enemy use your blade against you
EquipCharacterByItem(attack, enemy_blade); // and enables you to get it back by killing him/her
EquipCharacterByItem(enemy, "bladeX4");
Log_SetStringToLog(TranslateString("","You were disarmed!"));
}
}
}
}
We experimented with that, but it ended up being set OFF by default.
I don't think it serves any real purpose anymore, since the bladedamage mod kind-of took over from it.
There's certainly a problem with enemies who attack you with a worn weapon, it breaks, you don't notice it, and you lose reputation for continuing to attack.
Either the enemy continues to fight with his fists (in which case: no problem), OR he gives up and tries to run away.
Only in the second case you would get the reputation loss. (And this second case never happens in boardings.)
I don't think fighting, let alone killing, someone who is running away is a very respectable thing to do; so the reputation loss makes sense.
I can see the problem though when it just happened and you haven't had the chance to notice it.
At sea, a similar situation applies to ships that surrender in the middle of a cannon volley.
This is why there is a 'grace period' coded in per ship so that any hits
right after a surrender don't immediately trigger the reputation loss.
This doesn't happen on shore.
Adding this could be done here (also in PROGRAM\Loc_ai\LAi_events.c:
Code:
if(BladeBreak)
{
if(sti(enemy.index) == GetMainCharacterIndex()){
Continue_Bladedamage = false;
LogIt("Your blade decreased in quality!"); }
if(CheckAttribute(enemy, "nodisarm")) Continue_Bladedamage = false;
if(enemy.chr_ai.group == LAI_GROUP_PLAYER) Continue_Bladedamage = false;
if(bAbordageStarted) Continue_Bladedamage = false;
if(Continue_Bladedamage && rand(1) > 0)
{
LAi_SetCitizenTypeNoGroup(enemy);
}
else
{
if(CheckCharacterItem(enemy, FindCharacterItemByGroup(enemy, BLADE_ITEM_TYPE)) && GetItemQualityByID(FindCharacterItemByGroup(enemy, BLADE_ITEM_TYPE)) != 0 && BLADEDAMAGE_USEOTHERBLADE)
// If character has another blade and the other blade is not broken and USEOTHERBLADE is on
{
// Then use the other blade
EquipCharacterByItem(enemy, FindCharacterItemByGroup(enemy, BLADE_ITEM_TYPE));
}
else
{
// Else use the default blade
if(!CheckCharacterItem(enemy, BLADEDAMAGE_DEFAULTBLADE))
{GiveItem2Character(enemy, BLADEDAMAGE_DEFAULTBLADE);}
// To prevent characters being given another defaultblade if they already have one
EquipCharacterByItem(enemy, BLADEDAMAGE_DEFAULTBLADE);
}
}
}
Would have to be next to the 'LAi_SetCitizenTypeNoGroup' line.
And here is an example of how to code a delayed execution of a custom function from PROGRAM\NK.c:
Code:
PostEvent("KrakenAttackFinished", delay, "i", rCharacter);
}
#event_handler("KrakenAttackFinished", "FinishKrakenAttack");
void FinishKrakenAttack()
{
ref pchar = GetMainCharacter();
aref rCharacter = GetEventData();
LogIt("Captain, the Kraken has finished its attack on the " + rCharacter.ship.name + "!");
if(CheckAttribute(pchar, "KrakenAttack")) PostEvent("EnableKraken", 5*60*1000);
}
Then again in LAi_events.c, this is where the reputation loss for unarmed victims is applied:
Code:
if(!isSetBalde)
{
// ccc mar05 REPLOSS tweak added
if(enemy.chr_ai.group != LAi_monsters_group)
{
if(!CheckAttribute(enemy,"corpse")) enemy.corpse = false; //Fix by levis
if(enemy.corpse==false) //Levis: fix so you won't get reploss from hitting corpses
{
if (!CheckAttribute(enemy,"pickgold") || GetCharacterEquipByGroup(attack, BLADE_ITEM_TYPE) != "bladeX3") // GR: no reploss if he robbed you and you use a thief's knife
{
if(GetAttribute(attack, "index") && sti(attack.index) == GetMainCharacterIndex()) LogIt(TranslateString("","CHANGE REP for player:") + " " + -REPLOSS + " - " + TranslateString("","undrawn blade 2")); // LDH 19Dec08
LAi_ChangeReputation(attack, - REPLOSS); // NK tempfix for un-drawn blades 04-17
}
}
}
//exp = 0.0;
}
(You knew that already; I see your initials there.
)
On a side-note... I think this code has never functioned as intended:
Code:
bool isSetBalde = (SendMessage(enemy, "ls", MSG_CHARACTER_EX_MSG, "IsSetBalde") != 0);
It should return whether a character has
drawn his/her blade.
But as far as I know, it only returns 'true' for characters who don't have a blade equipped
at all.
Which is stupid, because we can check that easily on the PROGRAM side;
without a need to ask the engine itself using 'SendMessage' .
I wonder if that was ever fixed in later releases like CoAS or TEHO...