I've been working on a quite major change in the equipcombat and unequipcombat functions in preparation for planned changes to the job functions. The return values of these functions will be changed from Void to Boolean. Changing the return type to Boolean will allow me to give bonuses or penalties for the girls in certain jobs if they're wearing armor and weapons (Such as security girl without a weapon and armor get penalties, or just give a bonus if they are wearing weapon and armor... Waitresses, barmaids, and singers wearing armor having a chance to scare away customers, etc.)
The equipcombat function will check to make sure the girl is wearing a weapon or armor. If she is not wearing at least an armor and one weapon, the function returns false. The function returns true if the girl is wearing at least an armor and weapon, and attempts to equip the girl with her best (as determined by cost) armor and weapon if the configuration file allows automatic combat equipping.
The unequipcombat function will check to make sure the girl is NOT wearing any weapon or armor. If she is wearing any weapon or armor, the function returns false. If the configuration file allows automatic combat equipping, it will attempt to remove any weapon or armor the girl is wearing, and if it is allowed to do so it will return true. Girls with some certain, more aggressive traits may refuse to remove their weapons and armor.
At this point, I've done nothing short of a full rewrite of the two functions. Here's the code, for anyone that's interested.
cgirls.h around line 840:
bool EquipCombat(sGirl* girl); // girl makes sure best armor and weapons are equipped, ready for combat
bool UnequipCombat(sGirl* girl); // girl unequips armor and weapons, ready for brothel work or other non-aggressive jobs
cgirls.cpp starting around line 4100:
bool cGirls::EquipCombat(sGirl* girl)
{ // girl makes sure best armor and weapons are equipped, ready for combat.
// If this function finishes without the girl having at least an armor and one weapon, it returns false.
// First let's find out what's already equipped.
bool combatequips = false;
bool wearingArmor = false;
bool wearingWeap1 = false;
bool wearingWeap2 = false;
int Armor, Weap1, Weap2, oldArmor, oldWeap1, oldWeap2;
Armor = Weap1 = Weap2 = oldArmor = oldWeap1 = oldWeap2 = -1;
for(int i=0; i<40; i++)
{
if(girl->m_Inventory[i] != 0) // Is there something here?
{
sInventoryItem* curItem = girl->m_Inventory[i];
if((curItem->m_Type == INVWEAPON) || (curItem->m_Type == INVARMOR)) // Is it a weapon or armor?
combatequips = true; // She does have an armor or weapon in her inventory.
if((curItem->m_Type == INVWEAPON) && (girl->m_EquipedItems[i] != 0))
{ // I found a weapon that's already equipped.
if(wearingWeap1) // She's equipped with 2 weapons, and I already found the other.
{ // This is her second weapon.
wearingWeap2 = true;
Weap2 = oldWeap2 = i;
}
else
{ // This is her first weapon.
wearingWeap1 = true;
Weap1 = oldWeap1 = i;
}
}
if((curItem->m_Type == INVARMOR) && (girl->m_EquipedItems[i] != 0))
{ // I found the armor she has equipped.
wearingArmor = true;
Armor = oldArmor = i;
}
}
}
// If she doesn't have any armor or weapons in her inventory at all, nothing to do here.
if(!combatequips)
return false; // She's obviously not wearing an armor and one weapon.
cConfig cfg; // We'll store the config file values for later.
// The next bit assumes the cost of Weap1 is higher than the cost of Weap2. So...
if(wearingWeap1 && wearingWeap2)
{
if(girl->m_Inventory[Weap2]->m_Cost > girl->m_Inventory[Weap1]->m_Cost)
{
int temp;
temp = Weap1;
Weap1 = Weap2;
Weap2 = temp;
oldWeap1 = Weap1;
oldWeap2 = Weap2;
}
}
// Look at each item.
for(int i=0; i<40; i++)
{
if((girl->m_Inventory[i] != 0) && (girl->m_EquipedItems[i] = 0)) // Is it an item that's not equipped?
{
if(girl->m_Inventory[i]->m_Type == INVWEAPON) // Is it a weapon?
{
if(Weap1 != -1) // Does she already have one weapon?
{ //She already has one weapon.
if(girl->m_Inventory[i]->m_Cost > girl->m_Inventory[Weap1]->m_Cost) // Is this weapon better?
{ //This weapon is better. Switch the weapon already here to her second weapon, and use this weapon here.
Weap2 = Weap1;
Weap1 = i;
}
else
{ //The weapon she has here already is better. Look at her second weapon
if(Weap2 != -1) // Does she even have a second weapon?
{ //She already has a second weapon.
if(girl->m_Inventory[i]->m_Cost > girl->m_Inventory[Weap2]->m_Cost) // Is this weapon better?
Weap2 = i; // Yes. Use it.
}
else // She doesn't have a second weapon.
Weap2 = i; // Use this one.
}
}
else // She doesn't have any weapon.
Weap1 = i; // Use this one.
// If we made it here without changing weapons, both weapons she's wearing already are better.
}
if(girl->m_Inventory[i]->m_Type == INVARMOR) // Is it armor?
{
if(Armor != -1) // Is she already wearing any armor?
{ // She is wearing armor.
if(girl->m_Inventory[i]->m_Cost > girl->m_Inventory[Armor]->m_Cost) // Is this better?
Armor = i; // Yes. Use it.
}
else // She is not wearing armor.
Armor = i; // Use this.
// If we made it here without changing armor, the armor she's wearing is better.
}
}
}
// If she's not already wearing an armor and one weapon, and the configuration file doesn't allow autoequipping,
// then we need to end the function here. She isn't wearing an armor and at least one weapon, so returns false.
if(!wearingArmor && !wearingWeap1 && !cfg.items.auto_combat_equip())
return false;
// if she's retarded, she might refuse or forget
int refusal = 0;
int refused = false;
if(girl->has_trait("Retarded"))
refusal += 30;
if(g_Dice.percent(refusal))
refused = true;
// If we're changing her armor
if(Armor != oldArmor)
{
if(cfg.items.auto_combat_equip()) // Are we allowed to do this?
{
if (!refused) // Did the girl refuse?
{
if(wearingArmor) // If she's not wearing armor, there's nothing to unequip.
g_InvManager.Unequip(girl, oldArmor);
g_InvManager.Equip(girl, Armor, false); // Put on her best armor.
wearingArmor = true;
}
}
}
// If we're changing her first weapon
if(Weap1 != oldWeap1)
{
if(cfg.items.auto_combat_equip()) // Are we allowed to do this?
{
if(!refused) // Did the girl refuse?
{
if(wearingWeap1) // If she's not using a first weapon, there's nothing to unequip.
g_InvManager.Unequip(girl, oldWeap1);
g_InvManager.Equip(girl, Weap1, false); // Put on her best weapon.
wearingWeap1 = true;
}
}
}
// If we're changing her second weapon
if(Weap2 != oldWeap2)
{
if(cfg.items.auto_combat_equip()) // Are we allowed to do this?
{
if(!refused) // Did the girl refuse?
{
if(wearingWeap2) // If she's not using a second weapon, there's nothing to unequip.
g_InvManager.Unequip(girl, oldWeap2);
g_InvManager.Equip(girl, Weap2, false); // Put on her second best weapon.
wearingWeap2 = true;
}
}
}
/* We need to check again to see if she's wearing a weapon and armor. I'm not sure if she
* can actually make it here without having an armor and one weapon equipped, so this may
* just be a sanity check.
*/
if(!wearingArmor || !wearingWeap1)
return false;
return true; // If we made it here, she's at least wearing an armor and one weapon.
}
bool cGirls::UnequipCombat(sGirl* girl)
{ // girl unequips armor and weapons, ready for brothel work or other non-aggressive jobs
// First find out if she's wearing any in the first place
bool combatequips = false;
bool hasweaponorarmor = false;
for(int i=0; i<40; i++)
{
if(girl->m_Inventory != 0)
{ // I found an item. What is it?
sInventoryItem* curItem = girl->m_Inventory[i];
if ((curItem->m_Type == INVWEAPON) || (curItem->m_Type == INVARMOR)) // Is it weapon or armor?
{
hasweaponorarmor = true;
if(girl->m_EquipedItems != 0) // Is it equipped?
combatequips = true;
}
}
}
// If she doesn't have any armor or weapons, she's obviously not wearing any. Nothing to do here.
if(!hasweaponorarmor)
return true;
cConfig cfg; // Look at the configuration file, store values for later.
// if she's a really rough or crazy bitch, she might just keep combat gear equipped
int refusal = 0;
if(combatequips) // Is the crazy bitch even wearing anything?
{
if(girl->has_trait("Aggressive"))
refusal += 30;
if(girl->has_trait("Yandere"))
refusal += 30;
if(girl->has_trait("Twisted"))
refusal += 30;
if(girl->has_trait("Retarded"))
refusal += 30;
if(g_Dice.percent(refusal))
return false;
}
for(int i=0; i<40; i++)
{
if((girl->m_Inventory != 0) && (girl->m_EquipedItems[i] != 0))
{ // I found an equipped item.
sInventoryItem* curItem = girl->m_Inventory[i];
if(curItem->m_Type == INVWEAPON || curItem->m_Type == INVARMOR) // Is it armor or weapon?
{ // Yes, it's an equipped armor or weapon.
if(cfg.items.auto_combat_equip()) // Am I allowed to change this?
g_InvManager.Unequip(girl, i); // Yes, take it off.
else
return false; // I can't take it off. She'll be wearing armor or weapon after this function ends.
}
}
}
return true;
}
Edit: A few tweaks to the code, I think I've got it watertight now.