diff options
| -rw-r--r-- | engines/dm/champion.cpp | 5009 | ||||
| -rw-r--r-- | engines/dm/champion.h | 1 | ||||
| -rw-r--r-- | engines/dm/console.cpp | 42 | ||||
| -rw-r--r-- | engines/dm/console.h | 5 | ||||
| -rw-r--r-- | engines/dm/dm.cpp | 13 | 
5 files changed, 2567 insertions, 2503 deletions
| diff --git a/engines/dm/champion.cpp b/engines/dm/champion.cpp index cd59e2e049..fc24288804 100644 --- a/engines/dm/champion.cpp +++ b/engines/dm/champion.cpp @@ -1,2501 +1,2508 @@ -/* ScummVM - Graphic Adventure Engine
 -*
 -* ScummVM is the legal property of its developers, whose names
 -* are too numerous to list here. Please refer to the COPYRIGHT
 -* file distributed with this source distribution.
 -*
 -* This program is free software; you can redistribute it and/or
 -* modify it under the terms of the GNU General Public License
 -* as published by the Free Software Foundation; either version 2
 -* of the License, or (at your option) any later version.
 -*
 -* This program is distributed in the hope that it will be useful,
 -* but WITHOUT ANY WARRANTY; without even the implied warranty of
 -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 -* GNU General Public License for more details.
 -*
 -* You should have received a copy of the GNU General Public License
 -* along with this program; if not, write to the Free Software
 -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 -*
 -*/
 -
 -/*
 -* Based on the Reverse Engineering work of Christophe Fontanel,
 -* maintainer of the Dungeon Master Encyclopaedia (http://dmweb.free.fr/)
 -*/
 -
 -#include "champion.h"
 -#include "dungeonman.h"
 -#include "eventman.h"
 -#include "menus.h"
 -#include "inventory.h"
 -#include "objectman.h"
 -#include "text.h"
 -#include "timeline.h"
 -#include "projexpl.h"
 -#include "group.h"
 -#include "movesens.h"
 -
 -
 -namespace DM {
 -
 -const char *g417_baseSkillName[4] = {"FIGHTER", "NINJA", "PRIEST", "WIZARD"};
 -
 -Box gBoxMouth = Box(55, 72, 12, 29); // @ G0048_s_Graphic562_Box_Mouth 
 -Box gBoxEye = Box(11, 28, 12, 29); // @ G0049_s_Graphic562_Box_Eye 
 -Box g54_BoxChampionIcons[4] = {
 -	Box(281, 299,  0, 13),
 -	Box(301, 319,  0, 13),
 -	Box(301, 319, 15, 28),
 -	Box(281, 299, 15, 28)};
 -Color g46_ChampionColor[4] = {(Color)7, (Color)11, (Color)8, (Color)14};
 -
 -int16 g39_LightPowerToLightAmount[16] = {0, 5, 12, 24, 33, 40, 46, 51, 59, 68, 76, 82, 89, 94, 97, 100};
 -
 -uint16 gSlotMasks[38] = {  // @ G0038_ai_Graphic562_SlotMasks
 -						   /* 30 for champion inventory, 8 for chest */
 -	0xFFFF,   /* Ready Hand       Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Action Hand      Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0x0002,   /* Head             Head */
 -	0x0008,   /* Torso            Torso */
 -	0x0010,   /* Legs             Legs */
 -	0x0020,   /* Feet             Feet */
 -	0x0100,   /* Pouch 2          Pouch */
 -	0x0080,   /* Quiver Line2 1   Quiver 2 */
 -	0x0080,   /* Quiver Line1 2   Quiver 2 */
 -	0x0080,   /* Quiver Line2 2   Quiver 2 */
 -	0x0004,   /* Neck             Neck */
 -	0x0100,   /* Pouch 1          Pouch */
 -	0x0040,   /* Quiver Line1 1   Quiver 1 */
 -	0xFFFF,   /* Backpack Line1 1 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line2 2 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line2 3 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line2 4 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line2 5 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line2 6 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line2 7 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line2 8 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line2 9 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line1 2 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line1 3 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line1 4 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line1 5 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line1 6 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line1 7 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line1 8 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0xFFFF,   /* Backpack Line1 9 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
 -	0x0400,   /* Chest 1          Chest */
 -	0x0400,   /* Chest 2          Chest */
 -	0x0400,   /* Chest 3          Chest */
 -	0x0400,   /* Chest 4          Chest */
 -	0x0400,   /* Chest 5          Chest */
 -	0x0400,   /* Chest 6          Chest */
 -	0x0400,   /* Chest 7          Chest */
 -	0x0400}; /* Chest 8          Chest */
 -
 -Box gBoxChampionPortrait = Box(0, 31, 0, 28); // @ G0047_s_Graphic562_Box_ChampionPortrait 
 -
 -ChampionMan::ChampionMan(DMEngine *vm) : _vm(vm) {
 -	for (uint16 i = 0; i < 4; ++i) {
 -		_g409_championPendingDamage[i] = 0;
 -		_g410_championPendingWounds[i] = 0;
 -		_gK71_champions[i].resetToZero();
 -	}
 -	_g305_partyChampionCount = 0;
 -	_g303_partyDead = false;
 -	_g414_leaderHandObject = Thing(0);
 -	_g411_leaderIndex = kM1_ChampionNone;
 -	_g299_candidateChampionOrdinal = 0;
 -	_g300_partyIsSleeping = false;
 -	_g506_actingChampionOrdinal = 0;
 -	_g413_leaderHandObjectIconIndex = (IconIndice)0;
 -	_g415_leaderEmptyHanded = false;
 -	_g407_party.resetToZero();
 -	_g514_magicCasterChampionIndex = kM1_ChampionNone;
 -	_g420_mousePointerHiddenToDrawChangedObjIconOnScreen = false;
 -}
 -
 -bool ChampionMan::f329_isLeaderHandObjectThrown(int16 side) {
 -	if (_g411_leaderIndex == kM1_ChampionNone) {
 -		return false;
 -	}
 -	return f328_isObjectThrown(_g411_leaderIndex, kM1_ChampionSlotLeaderHand, side);
 -}
 -
 -bool ChampionMan::f328_isObjectThrown(uint16 champIndex, int16 slotIndex, int16 side) {
 -	bool throwingLeaderHandObjectFl = false;
 -	Thing curThing;
 -	Champion *curChampion = nullptr;
 -	Thing actionHandThing;
 -
 -	if (slotIndex < 0) { /* Throw object in leader hand, which is temporarily placed in action hand */
 -		if (_g415_leaderEmptyHanded)
 -			return false;
 -
 -		curThing = f298_getObjectRemovedFromLeaderHand();
 -		curChampion = &_gK71_champions[champIndex];
 -		actionHandThing = curChampion->getSlot(k1_ChampionSlotActionHand);
 -		curChampion->setSlot(k1_ChampionSlotActionHand, curThing);
 -		slotIndex = k1_ChampionSlotActionHand;
 -		throwingLeaderHandObjectFl = true;
 -	}
 -
 -	int16 kineticEnergy = f312_getStrength(champIndex, slotIndex);
 -	if (throwingLeaderHandObjectFl) {
 -		// In this case, curChampion and actionHandThing are set.
 -		curChampion->setSlot((ChampionSlot)slotIndex, actionHandThing);
 -	} else {
 -		curThing = f300_getObjectRemovedFromSlot(champIndex, slotIndex);
 -		if (curThing == Thing::_none)
 -			return false;
 -	}
 -
 -	_vm->f064_SOUND_RequestPlay_CPSD(k16_soundCOMBAT_ATTACK_SKELETON_ANIMATED_ARMOUR_DETH_KNIGHT, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY, k1_soundModePlayIfPrioritized);
 -	f325_decrementStamina(champIndex, f305_getThrowingStaminaCost(curThing));
 -	f330_disableAction(champIndex, 4);
 -	int16 experience = 8;
 -	int16 weaponKineticEnergy = 1;
 -	if (curThing.getType() == k5_WeaponThingType) {
 -		experience += 4;
 -		WeaponInfo *curWeapon = _vm->_dungeonMan->f158_getWeaponInfo(curThing);
 -		if (curWeapon->_class <= k12_WeaponClassPoisinDart) {
 -			weaponKineticEnergy = curWeapon->_kineticEnergy;
 -			experience += weaponKineticEnergy >> 2;
 -		}
 -	}
 -	f304_addSkillExperience(champIndex, k10_ChampionSkillThrow, experience);
 -	kineticEnergy += weaponKineticEnergy;
 -	int16 skillLevel = f303_getSkillLevel((ChampionIndex)champIndex, k10_ChampionSkillThrow);
 -	kineticEnergy += _vm->getRandomNumber(16) + (kineticEnergy >> 1) + skillLevel;
 -	int16 attack = f26_getBoundedValue((uint16)40, (uint16)((skillLevel << 3) + _vm->getRandomNumber(32)), (uint16)200);
 -	int16 stepEnergy = MAX(5, 11 - skillLevel);
 -	_vm->_projexpl->f212_projectileCreate(curThing, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY,
 -										  M21_normalizeModulo4(_vm->_dungeonMan->_g308_partyDir + side),
 -										  _vm->_dungeonMan->_g308_partyDir, kineticEnergy, attack, stepEnergy);
 -	_vm->_g311_projectileDisableMovementTicks = 4;
 -	_vm->_g312_lastProjectileDisabledMovementDirection = _vm->_dungeonMan->_g308_partyDir;
 -	f292_drawChampionState((ChampionIndex)champIndex);
 -	return true;
 -}
 -
 -uint16 ChampionMan::M27_getChampionPortraitX(uint16 index) {
 -	return ((index) & 0x7) << 5;
 -}
 -
 -uint16 ChampionMan::M28_getChampionPortraitY(uint16 index) {
 -	return ((index) >> 3) * 29;
 -}
 -
 -int16 ChampionMan::f279_getDecodedValue(char *string, uint16 characterCount) {
 -	int val = 0;
 -	for (uint16 i = 0; i < characterCount; ++i) {
 -		val = (val << 4) + (string[i] - 'A');
 -	}
 -	return val;
 -}
 -
 -void ChampionMan::f289_drawHealthOrStaminaOrManaValue(int16 posY, int16 currVal, int16 maxVal) {
 -	Common::String tmp = f288_getStringFromInteger(currVal, true, 3);
 -	_vm->_textMan->f52_printToViewport(55, posY, k13_ColorLightestGray, tmp.c_str());
 -	_vm->_textMan->f52_printToViewport(73, posY, k13_ColorLightestGray, "/");
 -	tmp = f288_getStringFromInteger(maxVal, true, 3);
 -	_vm->_textMan->f52_printToViewport(79, posY, k13_ColorLightestGray, tmp.c_str());
 -}
 -
 -uint16 ChampionMan::M70_handSlotIndex(uint16 slotBoxIndex) {
 -	return slotBoxIndex & 0x1;
 -}
 -
 -Common::String ChampionMan::f288_getStringFromInteger(uint16 val, bool padding, uint16 paddingCharCount) {
 -	Common::String valToStr = Common::String::format("%d", val);
 -	Common::String result;
 -
 -	if (padding) {
 -		for (int16 i = 0, end = paddingCharCount - valToStr.size(); i < end; ++i)
 -			result += ' ';
 -	}
 -
 -	return result += valToStr;
 -}
 -
 -void ChampionMan::f299_applyModifiersToStatistics(Champion *champ, int16 slotIndex, int16 iconIndex, int16 modifierFactor, Thing thing) {
 -	int16 statIndex = k0_ChampionStatLuck;
 -	int16 modifier = 0;
 -	ThingType thingType = thing.getType();
 -
 -	bool cursed = false;
 -	if (((thingType == k5_WeaponThingType) || (thingType == k6_ArmourThingType))
 -		&& (slotIndex >= k0_ChampionSlotReadyHand) && (slotIndex <= k12_ChampionSlotQuiverLine_1_1)) {
 -		if (thingType == k5_WeaponThingType) {
 -			Weapon *weapon = (Weapon *)_vm->_dungeonMan->f156_getThingData(thing);
 -			cursed = weapon->getCursed();
 -		} else {
 -			// k6_ArmourThingType
 -			Armour *armour = (Armour *)_vm->_dungeonMan->f156_getThingData(thing);
 -			cursed = armour->getCursed();
 -		}
 -
 -		if (cursed) {
 -			statIndex = k0_ChampionStatLuck;
 -			modifier = -3;
 -		}
 -	}
 -
 -	if (!cursed) {
 -		statIndex = (ChampionStatisticType)thingType; // variable sharing
 -
 -		if ((iconIndex == k137_IconIndiceJunkRabbitsFoot) && (slotIndex < k30_ChampionSlotChest_1)) {
 -			statIndex = k0_ChampionStatLuck;
 -			modifier = 10;
 -		} else if (slotIndex == k1_ChampionSlotActionHand) {
 -			if (iconIndex == k45_IconIndiceWeaponMaceOfOrder) {
 -				statIndex = k1_ChampionStatStrength;
 -				modifier = 5;
 -			} else {
 -				statIndex = k8_ChampionStatMana;
 -				if ((iconIndex >= k20_IconIndiceWeaponStaffOfClawsEmpty) && (iconIndex <= k22_IconIndiceWeaponStaffOfClawsFull)) {
 -					modifier = 4;
 -				} else {
 -					switch (iconIndex) {
 -					case k38_IconIndiceWeaponDeltaSideSplitter:
 -						modifier = 1;
 -						break;
 -					case k41_IconIndiceWeaponTheInquisitorDragonFang:
 -						modifier = 2;
 -						break;
 -					case k40_IconIndiceWeaponVorpalBlade:
 -						modifier = 4;
 -						break;
 -					case k58_IconIndiceWeaponStaff:
 -						modifier = 2;
 -						break;
 -					case k59_IconIndiceWeaponWand:
 -						modifier = 1;
 -						break;
 -					case k60_IconIndiceWeaponTeowand:
 -						modifier = 6;
 -						break;
 -					case k61_IconIndiceWeaponYewStaff:
 -						modifier = 4;
 -						break;
 -					case k62_IconIndiceWeaponStaffOfManarStaffOfIrra:
 -						modifier = 10;
 -						break;
 -					case k63_IconIndiceWeaponSnakeStaffCrossOfNeta:
 -						modifier = 8;
 -						break;
 -					case k64_IconIndiceWeaponTheConduitSerpentStaff:
 -						modifier = 16;
 -						break;
 -					case k65_IconIndiceWeaponDragonSpit:
 -						modifier = 7;
 -						break;
 -					case k66_IconIndiceWeaponSceptreOfLyf:
 -						modifier = 5;
 -						break;
 -					default:
 -						break;
 -					}
 -				}
 -			}
 -		} else if (slotIndex == k4_ChampionSlotLegs) {
 -			if (iconIndex == k142_IconIndiceArmourPowertowers) {
 -				statIndex = k1_ChampionStatStrength;
 -				modifier = 10;
 -			}
 -		} else if (slotIndex == k2_ChampionSlotHead) {
 -			switch (iconIndex) {
 -			case k104_IconIndiceArmourCrownOfNerra:
 -				statIndex = k3_ChampionStatWisdom;
 -				modifier = 10;
 -				break;
 -			case k140_IconIndiceArmourDexhelm:
 -				statIndex = k2_ChampionStatDexterity;
 -				modifier = 10;
 -				break;
 -			default:
 -				break;
 -			}
 -		} else if (slotIndex == k3_ChampionSlotTorso) {
 -			switch (iconIndex) {
 -			case k141_IconIndiceArmourFlamebain:
 -				statIndex = k6_ChampionStatAntifire;
 -				modifier = 12;
 -				break;
 -			case k81_IconIndiceArmourCloakOfNight:
 -				statIndex = k2_ChampionStatDexterity;
 -				modifier = 8;
 -				break;
 -			default:
 -				break;
 -			}
 -		} else if (slotIndex == k10_ChampionSlotNeck) {
 -			switch (iconIndex) {
 -			case k10_IconIndiceJunkJewelSymalUnequipped:
 -			case k11_IconIndiceJunkJewelSymalEquipped:
 -				statIndex = k5_ChampionStatAntimagic;
 -				modifier = 15;
 -				break;
 -			case k81_IconIndiceArmourCloakOfNight:
 -				statIndex = k2_ChampionStatDexterity;
 -				modifier = 8;
 -				break;
 -			case k122_IconIndiceJunkMoonstone:
 -				statIndex = k8_ChampionStatMana;
 -				modifier = 3;
 -				break;
 -			default:
 -				break;
 -			}
 -		}
 -	}
 -
 -	if (modifier) {
 -		modifier *= modifierFactor;
 -		//statIndex is set when modifier is set
 -		if (statIndex == k8_ChampionStatMana) {
 -			champ->_maxMana += modifier;
 -		} else if (statIndex < k6_ChampionStatAntifire + 1) {
 -			for (uint16 statValIndex = k0_ChampionStatMaximum; statValIndex <= k2_ChampionStatMinimum; ++statValIndex) {
 -				champ->getStatistic((ChampionStatisticType)statIndex, (ChampionStatisticValue)statValIndex) += modifier;
 -			}
 -		}
 -	}
 -}
 -
 -bool ChampionMan::f295_hasObjectIconInSlotBoxChanged(int16 slotBoxIndex, Thing thing) {
 -	ObjectMan &objMan = *_vm->_objectMan;
 -
 -	IconIndice currIconIndex = objMan.f39_getIconIndexInSlotBox(slotBoxIndex);
 -	if (((currIconIndex < k32_IconIndiceWeaponDagger) && (currIconIndex >= k0_IconIndiceJunkCompassNorth))
 -		|| ((currIconIndex >= k148_IconIndicePotionMaPotionMonPotion) && (currIconIndex <= k163_IconIndicePotionWaterFlask))
 -		|| (currIconIndex == k195_IconIndicePotionEmptyFlask)) {
 -		IconIndice newIconIndex = objMan.f33_getIconIndex(thing);
 -		if (newIconIndex != currIconIndex) {
 -			if ((slotBoxIndex < k8_SlotBoxInventoryFirstSlot) && !_g420_mousePointerHiddenToDrawChangedObjIconOnScreen) {
 -				_g420_mousePointerHiddenToDrawChangedObjIconOnScreen = true;
 -				_vm->_eventMan->f77_hideMouse();
 -			}
 -			objMan.f38_drawIconInSlotBox(slotBoxIndex, newIconIndex);
 -			return true;
 -		}
 -	}
 -
 -	return false;
 -}
 -
 -void ChampionMan::f296_drawChangedObjectIcons() {
 -	InventoryMan &invMan = *_vm->_inventoryMan;
 -	ObjectMan &objMan = *_vm->_objectMan;
 -	MenuMan &menuMan = *_vm->_menuMan;
 -
 -	uint16 invChampOrdinal = invMan._g432_inventoryChampionOrdinal;
 -	if (_g299_candidateChampionOrdinal && !invChampOrdinal)
 -		return;
 -
 -	_g420_mousePointerHiddenToDrawChangedObjIconOnScreen = false;
 -	IconIndice leaderHandObjIconIndex = _g413_leaderHandObjectIconIndex;
 -
 -	if (((leaderHandObjIconIndex < k32_IconIndiceWeaponDagger) && (leaderHandObjIconIndex >= k0_IconIndiceJunkCompassNorth))	// < instead of <= is correct
 -		|| ((leaderHandObjIconIndex >= k148_IconIndicePotionMaPotionMonPotion) && (leaderHandObjIconIndex <= k163_IconIndicePotionWaterFlask))
 -		|| (leaderHandObjIconIndex == k195_IconIndicePotionEmptyFlask)) {
 -		IconIndice iconIndex = objMan.f33_getIconIndex(_g414_leaderHandObject);
 -		if (iconIndex != leaderHandObjIconIndex) {
 -			_g420_mousePointerHiddenToDrawChangedObjIconOnScreen = true;
 -			_vm->_eventMan->f77_hideMouse();
 -			objMan.f36_extractIconFromBitmap(iconIndex, objMan._g412_objectIconForMousePointer);
 -			_vm->_eventMan->f68_setPointerToObject(_vm->_objectMan->_g412_objectIconForMousePointer);
 -			_g413_leaderHandObjectIconIndex = iconIndex;
 -			objMan.f34_drawLeaderObjectName(_g414_leaderHandObject);
 -		}
 -	}
 -
 -	for (uint16 slotBoxIndex = 0; slotBoxIndex < (_g305_partyChampionCount * 2); ++slotBoxIndex) {
 -		int16 champIndex = slotBoxIndex >> 1;
 -		if (invChampOrdinal == _vm->M0_indexToOrdinal(champIndex))
 -			continue;
 -
 -		if (f295_hasObjectIconInSlotBoxChanged(slotBoxIndex, _gK71_champions[champIndex].getSlot((ChampionSlot)M70_handSlotIndex(slotBoxIndex)))
 -			&& (M70_handSlotIndex(slotBoxIndex) == k1_ChampionSlotActionHand)) {
 -
 -			menuMan.f386_drawActionIcon((ChampionIndex)champIndex);
 -		}
 -	}
 -
 -	if (invChampOrdinal) {
 -		Champion *champ = &_gK71_champions[_vm->M1_ordinalToIndex(invChampOrdinal)];
 -		Thing *thing = &champ->getSlot(k0_ChampionSlotReadyHand);
 -		uint16 drawViewport = 0;
 -
 -		for (uint16 slotIndex = k0_ChampionSlotReadyHand; slotIndex < k30_ChampionSlotChest_1; slotIndex++, thing++) {
 -			uint16 objIconChanged = f295_hasObjectIconInSlotBoxChanged(slotIndex + k8_SlotBoxInventoryFirstSlot, *thing) ? 1 : 0;
 -			drawViewport |= objIconChanged;
 -			if (objIconChanged && (slotIndex == k1_ChampionSlotActionHand)) {
 -				menuMan.f386_drawActionIcon((ChampionIndex)_vm->M1_ordinalToIndex(invChampOrdinal));
 -			}
 -		}
 -
 -		if (invMan._g424_panelContent = k4_PanelContentChest) {
 -			thing = invMan._g425_chestSlots;
 -			for (int16 slotIndex = 0; slotIndex < 8; ++slotIndex, thing++) {
 -				drawViewport |= (f295_hasObjectIconInSlotBoxChanged(slotIndex + k38_SlotBoxChestFirstSlot, *thing) ? 1 : 0);
 -			}
 -		}
 -
 -		if (drawViewport) {
 -			champ->setAttributeFlag(k0x4000_ChampionAttributeViewport, true);
 -			f292_drawChampionState((ChampionIndex)_vm->M1_ordinalToIndex(invChampOrdinal));
 -		}
 -	}
 -
 -	if (_g420_mousePointerHiddenToDrawChangedObjIconOnScreen)
 -		_vm->_eventMan->f78_showMouse();
 -}
 -
 -void ChampionMan::f301_addObjectInSlot(ChampionIndex champIndex, Thing thing, ChampionSlot slotIndex) {
 -	InventoryMan &invMan = *_vm->_inventoryMan;
 -	DungeonMan &dunMan = *_vm->_dungeonMan;
 -	ObjectMan &objMan = *_vm->_objectMan;
 -	MenuMan &menuMan = *_vm->_menuMan;
 -
 -	if (thing == Thing::_none)
 -		return;
 -
 -	Champion *champ = &_gK71_champions[champIndex];
 -
 -	if (slotIndex >= k30_ChampionSlotChest_1) {
 -		invMan._g425_chestSlots[slotIndex - k30_ChampionSlotChest_1] = thing;
 -	} else {
 -		champ->setSlot(slotIndex, thing);
 -	}
 -
 -	champ->_load += dunMan.f140_getObjectWeight(thing);
 -	champ->setAttributeFlag(k0x0200_ChampionAttributeLoad, true);
 -	IconIndice iconIndex = objMan.f33_getIconIndex(thing);
 -	bool isInventoryChampion = (_vm->M0_indexToOrdinal(champIndex) == invMan._g432_inventoryChampionOrdinal);
 -	f299_applyModifiersToStatistics(champ, slotIndex, iconIndex, 1, thing);
 -	uint16 *rawObjPtr = dunMan.f156_getThingData(thing);
 -
 -	if (slotIndex < k2_ChampionSlotHead) {
 -		if (slotIndex == k1_ChampionSlotActionHand) {
 -			champ->setAttributeFlag(k0x8000_ChampionAttributeActionHand, true);
 -			if (_g506_actingChampionOrdinal == _vm->M0_indexToOrdinal(champIndex))
 -				menuMan.f388_clearActingChampion();
 -
 -			if ((iconIndex >= k30_IconIndiceScrollOpen) && (iconIndex <= k31_IconIndiceScrollClosed)) {
 -				((Scroll *)rawObjPtr)->setClosed(false);
 -				f296_drawChangedObjectIcons();
 -			}
 -		}
 -
 -		if (iconIndex = k4_IconIndiceWeaponTorchUnlit) {
 -			((Weapon *)rawObjPtr)->setLit(true);
 -			_vm->_inventoryMan->f337_setDungeonViewPalette();
 -			f296_drawChangedObjectIcons();
 -		} else if (isInventoryChampion && (slotIndex == k1_ChampionSlotActionHand) &&
 -			((iconIndex == k144_IconIndiceContainerChestClosed) || ((iconIndex >= k30_IconIndiceScrollOpen) && (iconIndex <= k31_IconIndiceScrollClosed)))) {
 -			champ->setAttributeFlag(k0x0800_ChampionAttributePanel, true);
 -		}
 -	} else if (slotIndex == k10_ChampionSlotNeck) {
 -		if ((iconIndex >= k12_IconIndiceJunkIllumuletUnequipped) && (iconIndex <= k13_IconIndiceJunkIllumuletEquipped)) {
 -			((Junk *)rawObjPtr)->setChargeCount(1);
 -			_g407_party._magicalLightAmount += g39_LightPowerToLightAmount[2];
 -			_vm->_inventoryMan->f337_setDungeonViewPalette();
 -			iconIndex = (IconIndice)(iconIndex + 1);
 -		} else if ((iconIndex >= k10_IconIndiceJunkJewelSymalUnequipped) && (iconIndex <= k11_IconIndiceJunkJewelSymalEquipped)) {
 -			((Junk *)rawObjPtr)->setChargeCount(1);
 -			iconIndex = (IconIndice)(iconIndex + 1);
 -		}
 -	}
 -
 -	f291_drawSlot(champIndex, slotIndex);
 -	if (isInventoryChampion)
 -		champ->setAttributeFlag(k0x4000_ChampionAttributeViewport, true);
 -}
 -
 -int16 ChampionMan::f315_getScentOrdinal(int16 mapX, int16 mapY) {
 -	int16 scentIndex = _g407_party._scentCount;
 -
 -	if (scentIndex) {
 -		Scent searchedScent;
 -		searchedScent.setMapX(mapX);
 -		searchedScent.setMapY(mapY);
 -		searchedScent.setMapIndex(_vm->_dungeonMan->_g272_currMapIndex);
 -		uint16 searchedScentRedEagle = searchedScent.toUint16();
 -		Scent *scent = &_g407_party._scents[scentIndex--];
 -		do {
 -			if ((*(--scent)).toUint16() == searchedScentRedEagle) {
 -				return _vm->M0_indexToOrdinal(scentIndex);
 -			}
 -		} while (scentIndex--);
 -	}
 -	return 0;
 -}
 -
 -Thing ChampionMan::f298_getObjectRemovedFromLeaderHand() {
 -	_g415_leaderEmptyHanded = true;
 -	Thing leaderHandObject = _g414_leaderHandObject;
 -
 -	if (leaderHandObject != Thing::_none) {
 -		_g414_leaderHandObject = Thing::_none;
 -		_g413_leaderHandObjectIconIndex = kM1_IconIndiceNone;
 -		_vm->_eventMan->f78_showMouse();
 -		_vm->_objectMan->f35_clearLeaderObjectName();
 -		_vm->_eventMan->f69_setMousePointer();
 -		_vm->_eventMan->f77_hideMouse();
 -		if (_g411_leaderIndex != kM1_ChampionNone) {
 -			_gK71_champions[_g411_leaderIndex]._load -= _vm->_dungeonMan->f140_getObjectWeight(leaderHandObject);
 -			setFlag(_gK71_champions[_g411_leaderIndex]._attributes, k0x0200_ChampionAttributeLoad);
 -			f292_drawChampionState(_g411_leaderIndex);
 -		}
 -	}
 -	return leaderHandObject;
 -}
 -
 -uint16 ChampionMan::f312_getStrength(int16 champIndex, int16 slotIndex) {
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	int16 strength = _vm->getRandomNumber(16) + curChampion->_statistics[k1_ChampionStatStrength][k1_ChampionStatCurrent];
 -	Thing curThing = curChampion->_slots[slotIndex];
 -	uint16 objectWeight = _vm->_dungeonMan->f140_getObjectWeight(curThing);
 -	uint16 oneSixteenthMaximumLoad = f309_getMaximumLoad(curChampion) >> 4;
 -
 -	if (objectWeight <= oneSixteenthMaximumLoad) {
 -		strength += objectWeight - 12;
 -	} else {
 -		int16 loadThreshold = oneSixteenthMaximumLoad + ((oneSixteenthMaximumLoad - 12) >> 1);
 -		if (objectWeight <= loadThreshold) {
 -			strength += (objectWeight - oneSixteenthMaximumLoad) >> 1;
 -		} else {
 -			strength -= (objectWeight - loadThreshold) << 1;
 -		}
 -	}
 -	if (curThing.getType() == k5_WeaponThingType) {
 -		WeaponInfo *weaponInfo = _vm->_dungeonMan->f158_getWeaponInfo(curThing);
 -		strength += weaponInfo->_strength;
 -		uint16 skillLevel = 0;
 -		uint16 weaponClass = weaponInfo->_class;
 -		if ((weaponClass == k0_WeaponClassSwingWeapon) || (weaponClass == k2_WeaponClassDaggerAndAxes)) {
 -			skillLevel = f303_getSkillLevel(champIndex, k4_ChampionSkillSwing);
 -		}
 -		if ((weaponClass != k0_WeaponClassSwingWeapon) && (weaponClass < k16_WeaponClassFirstBow)) {
 -			skillLevel += f303_getSkillLevel(champIndex, k10_ChampionSkillThrow);
 -		}
 -		if ((weaponClass >= k16_WeaponClassFirstBow) && (weaponClass < k112_WeaponClassFirstMagicWeapon)) {
 -			skillLevel += f303_getSkillLevel(champIndex, k11_ChampionSkillShoot);
 -		}
 -		strength += skillLevel << 1;
 -	}
 -	strength = f306_getStaminaAdjustedValue(curChampion, strength);
 -	if (getFlag(curChampion->_wounds, (slotIndex == k0_ChampionSlotReadyHand) ? k0x0001_ChampionWoundReadHand : k0x0002_ChampionWoundActionHand)) {
 -		strength >>= 1;
 -	}
 -	return f26_getBoundedValue(0, strength >> 1, 100);
 -}
 -
 -Thing ChampionMan::f300_getObjectRemovedFromSlot(uint16 champIndex, uint16 slotIndex) {
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	Thing curThing;
 -
 -	if (slotIndex >= k30_ChampionSlotChest_1) {
 -		curThing = _vm->_inventoryMan->_g425_chestSlots[slotIndex - k30_ChampionSlotChest_1];
 -		_vm->_inventoryMan->_g425_chestSlots[slotIndex - k30_ChampionSlotChest_1] = Thing::_none;
 -	} else {
 -		curThing = curChampion->_slots[slotIndex];
 -		curChampion->_slots[slotIndex] = Thing::_none;
 -	}
 -
 -	if (curThing == Thing::_none)
 -		return Thing::_none;
 -
 -	bool isInventoryChampion = (_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal);
 -	int16 curIconIndex = _vm->_objectMan->f33_getIconIndex(curThing);
 -	// Remove object modifiers
 -	f299_applyModifiersToStatistics(curChampion, slotIndex, curIconIndex, -1, curThing);
 -
 -	Weapon *curWeapon = (Weapon *)_vm->_dungeonMan->f156_getThingData(curThing);
 -	if (slotIndex == k10_ChampionSlotNeck) {
 -		if ((curIconIndex >= k12_IconIndiceJunkIllumuletUnequipped) && (curIconIndex <= k13_IconIndiceJunkIllumuletEquipped)) {
 -			((Junk *)curWeapon)->setChargeCount(0);
 -			_g407_party._magicalLightAmount -= g39_LightPowerToLightAmount[2];
 -			_vm->_inventoryMan->f337_setDungeonViewPalette();
 -		} else if ((curIconIndex >= k10_IconIndiceJunkJewelSymalUnequipped) && (curIconIndex <= k11_IconIndiceJunkJewelSymalEquipped)) {
 -			((Junk *)curWeapon)->setChargeCount(0);
 -		}
 -	}
 -
 -	f291_drawSlot(champIndex, slotIndex);
 -	if (isInventoryChampion)
 -		setFlag(curChampion->_attributes, k0x4000_ChampionAttributeViewport);
 -
 -	if (slotIndex < k2_ChampionSlotHead) {
 -		if (slotIndex == k1_ChampionSlotActionHand) {
 -			setFlag(curChampion->_attributes, k0x8000_ChampionAttributeActionHand);
 -			if (_g506_actingChampionOrdinal == _vm->M0_indexToOrdinal(champIndex))
 -				_vm->_menuMan->f388_clearActingChampion();
 -
 -			if ((curIconIndex >= k30_IconIndiceScrollOpen) && (curIconIndex <= k31_IconIndiceScrollClosed)) {
 -				((Scroll *)curWeapon)->setClosed(true);
 -				f296_drawChangedObjectIcons();
 -			}
 -		}
 -
 -		if ((curIconIndex >= k4_IconIndiceWeaponTorchUnlit) && (curIconIndex <= k7_IconIndiceWeaponTorchLit)) {
 -			curWeapon->setLit(false);
 -			_vm->_inventoryMan->f337_setDungeonViewPalette();
 -			f296_drawChangedObjectIcons();
 -		}
 -
 -		if (isInventoryChampion && (slotIndex == k1_ChampionSlotActionHand)) {
 -			switch (curIconIndex) {
 -			case k144_IconIndiceContainerChestClosed:
 -				_vm->_inventoryMan->f334_closeChest();
 -			// No break on purpose
 -			case k30_IconIndiceScrollOpen:
 -			case k31_IconIndiceScrollClosed:
 -				setFlag(curChampion->_attributes, k0x0800_ChampionAttributePanel);
 -				break;
 -			default:
 -				break;
 -			}
 -		}
 -	}
 -	curChampion->_load -= _vm->_dungeonMan->f140_getObjectWeight(curThing);
 -	setFlag(curChampion->_attributes, k0x0200_ChampionAttributeLoad);
 -	return curThing;
 -}
 -
 -void ChampionMan::f325_decrementStamina(int16 championIndex, int16 decrement) {
 -	if (championIndex == kM1_ChampionNone)
 -		return;
 -
 -	Champion *curChampion = &_gK71_champions[championIndex];
 -	curChampion->_currStamina -= decrement;
 -
 -	int16 stamina = curChampion->_currStamina;
 -	if (stamina <= 0) {
 -		curChampion->_currStamina = 0;
 -		f321_addPendingDamageAndWounds_getDamage(championIndex, (-stamina) >> 1, k0x0000_ChampionWoundNone, k0_attackType_NORMAL);
 -	} else if (stamina > curChampion->_maxStamina) {
 -		curChampion->_currStamina = curChampion->_maxStamina;
 -	}
 -
 -	setFlag(curChampion->_attributes, k0x0200_ChampionAttributeLoad | k0x0100_ChampionAttributeStatistics);
 -}
 -
 -int16 ChampionMan::f321_addPendingDamageAndWounds_getDamage(int16 champIndex, int16 attack, int16 allowedWounds, uint16 attackType) {
 -	if (attack <= 0)
 -		return 0;
 -
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	if (!curChampion->_currHealth)
 -		return 0;
 -
 -	bool skipScaling = false;
 -	if (attackType != k0_attackType_NORMAL) {
 -		uint16 defense = 0;
 -		uint16 woundCount = 0;
 -		for (int16 woundIndex = k0_ChampionSlotReadyHand; woundIndex <= k5_ChampionSlotFeet; woundIndex++) {
 -			if (allowedWounds & (1 << woundIndex)) {
 -				woundCount++;
 -				defense += f313_getWoundDefense(champIndex, woundIndex | ((attackType == k4_attackType_SHARP) ? k0x8000_maskUseSharpDefense : k0x0000_maskDoNotUseSharpDefense));
 -			}
 -		}
 -		if (woundCount)
 -			defense /= woundCount;
 -
 -		switch (attackType) {
 -		case k6_attackType_PSYCHIC:
 -		{
 -			int16 wisdomFactor = 115 - curChampion->_statistics[k3_ChampionStatWisdom][k1_ChampionStatCurrent];
 -			if (wisdomFactor <= 0) {
 -				attack = 0;
 -			} else {
 -				attack = _vm->f30_getScaledProduct(attack, 6, wisdomFactor);
 -			}
 -
 -			skipScaling = true;
 -		}
 -		break;
 -		case k5_attackType_MAGIC:
 -			attack = f307_getStatisticAdjustedAttack(curChampion, k5_ChampionStatAntimagic, attack);
 -			attack -= _g407_party._spellShieldDefense;
 -			skipScaling = true;
 -			break;
 -		case k1_attackType_FIRE:
 -			attack = f307_getStatisticAdjustedAttack(curChampion, k6_ChampionStatAntifire, attack);
 -			attack -= _g407_party._fireShieldDefense;
 -			break;
 -		case k2_attackType_SELF:
 -			defense >>= 1;
 -			break;
 -		default:
 -			break;
 -		}
 -
 -		if (!skipScaling) {
 -			if (attack <= 0)
 -				return 0;
 -
 -			attack = _vm->f30_getScaledProduct(attack, 6, 130 - defense);
 -		}
 -		/* BUG0_44
 -			A champion may take much more damage than expected after a Black Flame attack or an impact
 -			with a Fireball projectile. If the party has a fire shield defense value higher than the fire
 -			attack value then the resulting intermediary attack value is negative and damage should be 0.
 -			However, the negative value is still used for further computations and the result may be a very
 -			high positive attack value which may kill a champion. This can occur only for k1_attackType_FIRE
 -			and if attack is negative before calling F0030_MAIN_GetScaledProduct
 -		*/
 -
 -		if (attack <= 0)
 -			return 0;
 -
 -		int16 adjustedAttack = f307_getStatisticAdjustedAttack(curChampion, k4_ChampionStatVitality, _vm->getRandomNumber(128) + 10);
 -		if (attack > adjustedAttack) {
 -		/* BUG0_45
 -			This bug is not perceptible because of BUG0_41 that ignores Vitality while determining the
 -			probability of being wounded. However if it was fixed, the behavior would be the opposite
 -			of what it should: the higher the vitality of a champion, the lower the result of
 -			F0307_CHAMPION_GetStatisticAdjustedAttack and the more likely the champion could get
 -			wounded (because of more iterations in the loop below)
 -		*/
 -			do {
 -				setFlag(*(uint16 *)&_g410_championPendingWounds[champIndex], (1 << _vm->getRandomNumber(8)) & allowedWounds);
 -			} while ((attack > (adjustedAttack <<= 1)) && adjustedAttack);
 -		}
 -
 -		if (_g300_partyIsSleeping)
 -			f314_wakeUp();
 -	}
 -	_g409_championPendingDamage[champIndex] += attack;
 -	return attack;
 -}
 -
 -int16 ChampionMan::f313_getWoundDefense(int16 champIndex, uint16 woundIndex) {
 -	static const byte woundDefenseFactor[6] = {5, 5, 4, 6, 3, 1}; // @ G0050_auc_Graphic562_WoundDefenseFactor
 -
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	bool useSharpDefense = getFlag(woundIndex, k0x8000_maskUseSharpDefense);
 -	if (useSharpDefense)
 -		clearFlag(woundIndex, k0x8000_maskUseSharpDefense);
 -
 -	uint16 armorShieldDefense = 0;
 -	for (int16 slotIndex = k0_ChampionSlotReadyHand; slotIndex <= k1_ChampionSlotActionHand; slotIndex++) {
 -		Thing curThing = curChampion->_slots[slotIndex];
 -		if (curThing.getType() == k6_ArmourThingType) {
 -			ArmourInfo *armorInfo = (ArmourInfo *)_vm->_dungeonMan->f156_getThingData(curThing);
 -			armorInfo = &g239_ArmourInfo[((Armour *)armorInfo)->getType()];
 -			if (getFlag(armorInfo->_attributes, k0x0080_ArmourAttributeIsAShield))
 -				armorShieldDefense += ((f312_getStrength(champIndex, slotIndex) + _vm->_dungeonMan->f143_getArmourDefense(armorInfo, useSharpDefense)) * woundDefenseFactor[woundIndex]) >> ((slotIndex == woundIndex) ? 4 : 5);
 -		}
 -	}
 -
 -	int16 woundDefense = _vm->getRandomNumber((curChampion->_statistics[k4_ChampionStatVitality][k1_ChampionStatCurrent] >> 3) + 1);
 -	if (useSharpDefense)
 -		woundDefense >>= 1;
 -
 -	woundDefense += curChampion->_actionDefense + curChampion->_shieldDefense + _g407_party._shieldDefense + armorShieldDefense;
 -	if (woundIndex > k1_ChampionSlotActionHand) {
 -		Thing curThing = curChampion->_slots[woundIndex];
 -		if (curThing.getType() == k6_ArmourThingType) {
 -			ArmourInfo *armourInfo = (ArmourInfo *)_vm->_dungeonMan->f156_getThingData(curThing);
 -			woundDefense += _vm->_dungeonMan->f143_getArmourDefense(&g239_ArmourInfo[((Armour *)armourInfo)->getType()], useSharpDefense);
 -		}
 -	}
 -
 -	if (getFlag(curChampion->_wounds, 1 << woundIndex))
 -		woundDefense -= 8 + _vm->getRandomNumber(4);
 -
 -	if (_g300_partyIsSleeping)
 -		woundDefense >>= 1;
 -
 -	return f26_getBoundedValue(0, woundDefense >> 1, 100);
 -}
 -
 -uint16 ChampionMan::f307_getStatisticAdjustedAttack(Champion *champ, uint16 statIndex, uint16 attack) {
 -	int16 factor = 170 - champ->_statistics[statIndex][k1_ChampionStatCurrent];
 -
 -	/* BUG0_41
 -		The Antifire and Antimagic statistics are completely ignored. The Vitality statistic is ignored
 -		against poison and to determine the probability of being wounded. Vitality is still used normally
 -		to compute the defense against wounds and the speed of health regeneration. A bug in the Megamax C
 -		compiler produces wrong machine code for this statement. It always returns 0 for the current statistic
 -		value so that factor = 170 in all cases
 -	*/
 -	if (factor < 16)
 -		return attack >> 3;
 -
 -	return _vm->f30_getScaledProduct(attack, 7, factor);
 -}
 -
 -void ChampionMan::f314_wakeUp() {
 -	_vm->_g321_stopWaitingForPlayerInput = true;
 -	_g300_partyIsSleeping = false;
 -	_vm->_g318_waitForInputMaxVerticalBlankCount = 10;
 -	_vm->f22_delay(10);
 -	_vm->_displayMan->f98_drawFloorAndCeiling();
 -	_vm->_eventMan->_g441_primaryMouseInput = g447_PrimaryMouseInput_Interface;
 -	_vm->_eventMan->_g442_secondaryMouseInput = g448_SecondaryMouseInput_Movement;
 -	_vm->_eventMan->_g443_primaryKeyboardInput = g458_primaryKeyboardInput_interface;
 -	_vm->_eventMan->_g444_secondaryKeyboardInput = g459_secondaryKeyboardInput_movement;
 -	_vm->_eventMan->f357_discardAllInput();
 -	_vm->_menuMan->f457_drawEnabledMenus();
 -}
 -
 -int16 ChampionMan::f305_getThrowingStaminaCost(Thing thing) {
 -	int16 weight = _vm->_dungeonMan->f140_getObjectWeight(thing) >> 1;
 -	int16 staminaCost = f26_getBoundedValue<int16>(1, weight, 10);
 -
 -	while ((weight -= 10) > 0)
 -		staminaCost += weight >> 1;
 -
 -	return staminaCost;
 -}
 -
 -void ChampionMan::f330_disableAction(uint16 champIndex, uint16 ticks) {
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	int32 updatedEnableActionEventTime = _vm->_g313_gameTime + ticks;
 -
 -	TimelineEvent curEvent;
 -	curEvent._type = k11_TMEventTypeEnableChampionAction;
 -	curEvent._priority = champIndex;
 -	curEvent._B._slotOrdinal = 0;
 -
 -	int16 eventIndex = curChampion->_enableActionEventIndex;
 -	if (eventIndex >= 0) {
 -		int32 currentEnableActionEventTime = M30_time(_vm->_timeline->_g370_events[eventIndex]._mapTime);
 -		if (updatedEnableActionEventTime >= currentEnableActionEventTime) {
 -			updatedEnableActionEventTime += (currentEnableActionEventTime - _vm->_g313_gameTime) >> 1;
 -		} else {
 -			updatedEnableActionEventTime = currentEnableActionEventTime + (ticks >> 1);
 -		}
 -		_vm->_timeline->f237_deleteEvent(eventIndex);
 -	} else {
 -		setFlag(curChampion->_attributes, k0x8000_ChampionAttributeActionHand | k0x0008_ChampionAttributeDisableAction);
 -		f292_drawChampionState((ChampionIndex)champIndex);
 -	}
 -	M33_setMapAndTime(curEvent._mapTime, _vm->_dungeonMan->_g309_partyMapIndex, updatedEnableActionEventTime);
 -	curChampion->_enableActionEventIndex = _vm->_timeline->f238_addEventGetEventIndex(&curEvent);
 -}
 -
 -void ChampionMan::f304_addSkillExperience(uint16 champIndex, uint16 skillIndex, uint16 exp) {
 -	if ((skillIndex >= k4_ChampionSkillSwing) && (skillIndex <= k11_ChampionSkillShoot) && (_vm->_projexpl->_g361_lastCreatureAttackTime < _vm->_g313_gameTime - 150))
 -		exp >>= 1;
 -
 -	if (exp) {
 -		if (_vm->_dungeonMan->_g269_currMap->_difficulty)
 -			exp *= _vm->_dungeonMan->_g269_currMap->_difficulty;
 -
 -		Champion *curChampion = &_gK71_champions[champIndex];
 -		uint16 baseSkillIndex;
 -		if (skillIndex >= k4_ChampionSkillSwing)
 -			baseSkillIndex = (skillIndex - k4_ChampionSkillSwing) >> 2;
 -		else
 -			baseSkillIndex = skillIndex;
 -
 -		uint16 skillLevelBefore = f303_getSkillLevel(champIndex, baseSkillIndex | (k0x4000_IgnoreObjectModifiers | k0x8000_IgnoreTemporaryExperience));
 -
 -		if ((skillIndex >= k4_ChampionSkillSwing) && (_vm->_projexpl->_g361_lastCreatureAttackTime > _vm->_g313_gameTime - 25))
 -			exp <<= 1;
 -
 -		Skill *curSkill = &curChampion->_skills[skillIndex];
 -		curSkill->_experience += exp;
 -		if (curSkill->_temporaryExperience < 32000)
 -			curSkill->_temporaryExperience += f26_getBoundedValue(1, exp >> 3, 100);
 -
 -		curSkill = &curChampion->_skills[baseSkillIndex];
 -		if (skillIndex >= k4_ChampionSkillSwing)
 -			curSkill->_experience += exp;
 -
 -		uint16 skillLevelAfter = f303_getSkillLevel(champIndex, baseSkillIndex | (k0x4000_IgnoreObjectModifiers | k0x8000_IgnoreTemporaryExperience));
 -		if (skillLevelAfter > skillLevelBefore) {
 -			int16 newBaseSkillLevel = skillLevelAfter;
 -			int16 minorStatIncrease = _vm->getRandomNumber(2);
 -			int16 majorStatIncrease = 1 + _vm->getRandomNumber(2);
 -			uint16 vitalityAmount = _vm->getRandomNumber(2); /* For Priest skill, the amount is 0 or 1 for all skill levels */
 -			if (baseSkillIndex != k2_ChampionSkillPriest) {
 -				vitalityAmount &= skillLevelAfter; /* For non Priest skills the amount is 0 for even skill levels. The amount is 0 or 1 for odd skill levels */
 -			}
 -			curChampion->_statistics[k4_ChampionStatVitality][k0_ChampionStatMaximum] += vitalityAmount;
 -			uint16 staminaAmount = curChampion->_maxStamina;
 -			curChampion->_statistics[k6_ChampionStatAntifire][k0_ChampionStatMaximum] += _vm->getRandomNumber(2) & ~skillLevelAfter; /* The amount is 0 for odd skill levels. The amount is 0 or 1 for even skill levels */
 -			bool increaseManaFl = false;
 -			switch (baseSkillIndex) {
 -			case k0_ChampionSkillFighter:
 -				staminaAmount >>= 4;
 -				skillLevelAfter *= 3;
 -				curChampion->_statistics[k1_ChampionStatStrength][k0_ChampionStatMaximum] += majorStatIncrease;
 -				curChampion->_statistics[k2_ChampionStatDexterity][k0_ChampionStatMaximum] += minorStatIncrease;
 -				break;
 -			case k1_ChampionSkillNinja:
 -				staminaAmount /= 21;
 -				skillLevelAfter <<= 1;
 -				curChampion->_statistics[k1_ChampionStatStrength][k0_ChampionStatMaximum] += minorStatIncrease;
 -				curChampion->_statistics[k2_ChampionStatDexterity][k0_ChampionStatMaximum] += majorStatIncrease;
 -				break;
 -			case k3_ChampionSkillWizard:
 -				staminaAmount >>= 5;
 -				curChampion->_maxMana += skillLevelAfter + (skillLevelAfter >> 1);
 -				curChampion->_statistics[k3_ChampionStatWisdom][k0_ChampionStatMaximum] += majorStatIncrease;
 -				increaseManaFl = true;
 -				break;
 -			case k2_ChampionSkillPriest:
 -				staminaAmount /= 25;
 -				curChampion->_maxMana += skillLevelAfter;
 -				skillLevelAfter += (skillLevelAfter + 1) >> 1;
 -				curChampion->_statistics[k3_ChampionStatWisdom][k0_ChampionStatMaximum] += minorStatIncrease;
 -				increaseManaFl = true;
 -				break;
 -			default:
 -				break;
 -			}
 -			if (increaseManaFl) {
 -				if ((curChampion->_maxMana += MIN(_vm->getRandomNumber(4), (uint16)(newBaseSkillLevel - 1))) > 900)
 -					curChampion->_maxMana = 900;
 -				curChampion->_statistics[k5_ChampionStatAntimagic][k0_ChampionStatMaximum] += _vm->getRandomNumber(3);
 -			}
 -
 -			if ((curChampion->_maxHealth += skillLevelAfter + _vm->getRandomNumber((skillLevelAfter >> 1) + 1)) > 999)
 -				curChampion->_maxHealth = 999;
 -
 -			if ((curChampion->_maxStamina += staminaAmount + _vm->getRandomNumber((staminaAmount >> 1) + 1)) > 9999)
 -				curChampion->_maxStamina = 9999;
 -
 -			setFlag(curChampion->_attributes, k0x0100_ChampionAttributeStatistics);
 -			f292_drawChampionState((ChampionIndex)champIndex);
 -			_vm->_textMan->f51_messageAreaPrintLineFeed();
 -			Color curChampionColor = g46_ChampionColor[champIndex];
 -			_vm->_textMan->f47_messageAreaPrintMessage(curChampionColor, curChampion->_name);
 -			// TODO: localization
 -			_vm->_textMan->f47_messageAreaPrintMessage(curChampionColor, " JUST GAINED A ");
 -			_vm->_textMan->f47_messageAreaPrintMessage(curChampionColor, g417_baseSkillName[baseSkillIndex]);
 -			_vm->_textMan->f47_messageAreaPrintMessage(curChampionColor, " LEVEL!");
 -		}
 -	}
 -}
 -
 -int16 ChampionMan::f324_damageAll_getDamagedChampionCount(uint16 attack, int16 wounds, int16 attackType) {
 -	int16 randomMax = (attack >> 3) + 1;
 -	uint16 reducedAttack = attack - randomMax;
 -	randomMax <<= 1;
 -
 -	int16 damagedChampionCount = 0;
 -	for (int16 championIndex = k0_ChampionFirst; championIndex < _g305_partyChampionCount; championIndex++) {
 -		// Actual attack is attack +/- (attack / 8)
 -		if (f321_addPendingDamageAndWounds_getDamage(championIndex, MAX(1, reducedAttack + _vm->getRandomNumber(randomMax)), wounds, attackType))
 -			damagedChampionCount++;
 -	}
 -
 -	return damagedChampionCount;
 -}
 -
 -int16 ChampionMan::f286_getTargetChampionIndex(int16 mapX, int16 mapY, uint16 cell) {
 -	if (_g305_partyChampionCount && (M38_distance(mapX, mapY, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY) <= 1)) {
 -		signed char orderedCellsToAttack[4];
 -		_vm->_groupMan->f229_setOrderedCellsToAttack(orderedCellsToAttack, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY, mapX, mapY, cell);
 -		for (uint16 i = 0; i < 4; i++) {
 -			int16 championIndex = f285_getIndexInCell(orderedCellsToAttack[i]);
 -			if (championIndex >= 0)
 -				return championIndex;
 -		}
 -	}
 -	return kM1_ChampionNone;
 -}
 -
 -int16 ChampionMan::f311_getDexterity(Champion* champ) {
 -	int16 dexterity = _vm->getRandomNumber(8) + champ->_statistics[k2_ChampionStatDexterity][k1_ChampionStatCurrent];
 -	dexterity -= ((int32)(dexterity >> 1) * (int32)champ->_load) / f309_getMaximumLoad(champ);
 -	if (_g300_partyIsSleeping)
 -		dexterity >>= 1;
 -
 -	return f26_getBoundedValue(1 + _vm->getRandomNumber(8), dexterity >> 1, 100 - _vm->getRandomNumber(8));
 -}
 -
 -bool ChampionMan::f308_isLucky(Champion* champ, uint16 percentage) {
 -	if (_vm->getRandomNumber(2) && (_vm->getRandomNumber(100) > percentage))
 -		return true;
 -
 -	unsigned char *curStat = champ->_statistics[k0_ChampionStatLuck];
 -	bool isLucky = (_vm->getRandomNumber(curStat[k1_ChampionStatCurrent]) > percentage);
 -	curStat[k1_ChampionStatCurrent] = f26_getBoundedValue<char>(curStat[k2_ChampionStatMinimum], curStat[k1_ChampionStatCurrent] + (isLucky ? -2 : 2), curStat[k0_ChampionStatMaximum]);
 -	return isLucky;
 -}
 -
 -void ChampionMan::f322_championPoison(int16 champIndex, uint16 attack) {
 -	if ((champIndex == kM1_ChampionNone) || (_vm->M0_indexToOrdinal(champIndex) == _g299_candidateChampionOrdinal))
 -		return;
 -
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	f321_addPendingDamageAndWounds_getDamage(champIndex, MAX(1, attack >> 6), k0x0000_ChampionWoundNone, k0_attackType_NORMAL);
 -	setFlag(curChampion->_attributes, k0x0100_ChampionAttributeStatistics);
 -	if ((_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) && (_vm->_inventoryMan->_g424_panelContent == k0_PanelContentFoodWaterPoisoned)) {
 -		setFlag(curChampion->_attributes, k0x0800_ChampionAttributePanel);
 -	}
 -
 -	if (--attack) {
 -		curChampion->_poisonEventCount++;
 -		TimelineEvent newEvent;
 -		newEvent._type = k75_TMEventTypePoisonChampion;
 -		newEvent._priority = champIndex;
 -		M33_setMapAndTime(newEvent._mapTime, _vm->_dungeonMan->_g309_partyMapIndex, _vm->_g313_gameTime + 36);
 -		newEvent._B._attack = attack;
 -		_vm->_timeline->f238_addEventGetEventIndex(&newEvent);
 -	}
 -
 -	f292_drawChampionState((ChampionIndex)champIndex);
 -}
 -
 -void ChampionMan::f284_setPartyDirection(int16 dir) {
 -	if (dir == _vm->_dungeonMan->_g308_partyDir)
 -		return;
 -
 -	int16 L0834_i_Delta = dir - _vm->_dungeonMan->_g308_partyDir;
 -	if (L0834_i_Delta < 0)
 -		L0834_i_Delta += 4;
 -
 -	Champion *curChampion = _gK71_champions;
 -	for (int16 i = k0_ChampionFirst; i < _g305_partyChampionCount; i++) {
 -		curChampion->_cell = (ViewCell)M21_normalizeModulo4(curChampion->_cell + L0834_i_Delta);
 -		curChampion->_dir = (Direction)M21_normalizeModulo4(curChampion->_dir + L0834_i_Delta);
 -		curChampion++;
 -	}
 -
 -	_vm->_dungeonMan->_g308_partyDir = (Direction)dir;
 -	f296_drawChangedObjectIcons();
 -}
 -
 -void ChampionMan::f316_deleteScent(uint16 scentIndex) {
 -	uint16 count = --_g407_party._scentCount - scentIndex;
 -
 -	if (count) {
 -		for (uint16 i = 0; i < count; ++i) {
 -			_g407_party._scents[scentIndex + i] = _g407_party._scents[scentIndex + i + 1];
 -			_g407_party._scentStrengths[scentIndex + i] = _g407_party._scentStrengths[scentIndex + i + 1];
 -		}
 -	}
 -
 -	if (scentIndex < _g407_party._firstScentIndex)
 -		_g407_party._firstScentIndex--;
 -
 -	if (scentIndex < _g407_party._lastScentIndex)
 -		_g407_party._lastScentIndex--;
 -}
 -
 -void ChampionMan::f317_addScentStrength(int16 mapX, int16 mapY, int32 cycleCount) {
 -	int16 scentIndex = _g407_party._scentCount;
 -	if (scentIndex) {
 -		bool mergeFl = getFlag(cycleCount, k0x8000_mergeCycles);
 -		if (mergeFl)
 -			clearFlag(cycleCount, k0x8000_mergeCycles);
 -
 -		Scent newScent; /* BUG0_00 Useless code */
 -		newScent.setMapX(mapX); /* BUG0_00 Useless code */
 -		newScent.setMapY(mapY); /* BUG0_00 Useless code */
 -		newScent.setMapIndex(_vm->_dungeonMan->_g272_currMapIndex); /* BUG0_00 Useless code */
 -
 -		Scent *curScent = _g407_party._scents; /* BUG0_00 Useless code */
 -		bool cycleCountDefined = false;
 -		while (scentIndex--) {
 -			if (&*curScent++ == &newScent) {
 -				if (!cycleCountDefined) {
 -					cycleCountDefined = true;
 -					if (mergeFl) {
 -						cycleCount = MAX<int32>(_g407_party._scentStrengths[scentIndex], cycleCount);
 -					} else {
 -						cycleCount = MIN<int32>(80, _g407_party._scentStrengths[scentIndex] + cycleCount);
 -					}
 -				}
 -				_g407_party._scentStrengths[scentIndex] = cycleCount;
 -			}
 -		}
 -	}
 -}
 -
 -void ChampionMan::f297_putObjectInLeaderHand(Thing thing, bool setMousePointer) {
 -	if (thing == Thing::_none)
 -		return;
 -
 -	_g415_leaderEmptyHanded = false;
 -	_vm->_objectMan->f36_extractIconFromBitmap(_g413_leaderHandObjectIconIndex = _vm->_objectMan->f33_getIconIndex(_g414_leaderHandObject = thing), _vm->_objectMan->_g412_objectIconForMousePointer);
 -	_vm->_eventMan->f78_showMouse();
 -	_vm->_objectMan->f34_drawLeaderObjectName(thing);
 -
 -	if (setMousePointer)
 -		_vm->_g325_setMousePointerToObjectInMainLoop = true;
 -	else
 -		_vm->_eventMan->f68_setPointerToObject(_vm->_objectMan->_g412_objectIconForMousePointer);
 -
 -	_vm->_eventMan->f77_hideMouse();
 -	if (_g411_leaderIndex != kM1_ChampionNone) {
 -		_gK71_champions[_g411_leaderIndex]._load += _vm->_dungeonMan->f140_getObjectWeight(thing);
 -		setFlag(_gK71_champions[_g411_leaderIndex]._attributes, k0x0200_ChampionAttributeLoad);
 -		f292_drawChampionState(_g411_leaderIndex);
 -	}
 -}
 -
 -int16 ChampionMan::f310_getMovementTicks(Champion *champ) {
 -	uint16 maximumLoad = f309_getMaximumLoad(champ);
 -	uint16 curLoad = champ->_load;
 -	uint16 woundTicks;
 -	int16 ticks;
 -	/* BUG0_72 - Fixed
 -		The party moves very slowly even though no champion 'Load' value is drawn in red.
 -		When the Load of a champion has exactly the maximum value he can carry then the Load
 -		is drawn in yellow but the speed is the same as when the champion is overloaded
 -		(when the Load is drawn in red). The comparison operator should be >= instead of >
 -	*/
 -	if (maximumLoad >= curLoad) {
 -		ticks = 2;
 -		if (((int32)curLoad << 3) > ((int32)maximumLoad * 5))
 -			ticks++;
 -
 -		woundTicks = 1;
 -	} else {
 -		ticks = 4 + (((curLoad - maximumLoad) << 2) / maximumLoad);
 -		woundTicks = 2;
 -	}
 -
 -	if (getFlag(champ->_wounds, k0x0020_ChampionWoundFeet))
 -		ticks += woundTicks;
 -
 -	if (_vm->_objectMan->f33_getIconIndex(champ->_slots[k5_ChampionSlotFeet]) == k194_IconIndiceArmourBootOfSpeed)
 -		ticks--;
 -
 -	return ticks;
 -}
 -
 -bool ChampionMan::f294_isAmmunitionCompatibleWithWeapon(uint16 champIndex, uint16 weaponSlotIndex, uint16 ammunitionSlotIndex) {
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	Thing curThing = curChampion->_slots[weaponSlotIndex];
 -	if (curThing.getType() != k5_WeaponThingType)
 -		return false;
 -
 -	WeaponInfo *weaponInfo = _vm->_dungeonMan->f158_getWeaponInfo(curThing);
 -	int16 weaponClass = kM1_WeaponClassNone;
 -
 -	if ((weaponInfo->_class >= k16_WeaponClassFirstBow) && (weaponInfo->_class <= k31_WeaponClassLastBow))
 -		weaponClass = k10_WeaponClassBowAmmunition;
 -	else if ((weaponInfo->_class >= k32_WeaponClassFirstSling) && (weaponInfo->_class <= k47_WeaponClassLastSling))
 -		weaponClass = k11_WeaponClassSlingAmmunition;
 -
 -	if (weaponClass == kM1_WeaponClassNone)
 -		return false;
 -
 -	curThing = curChampion->_slots[ammunitionSlotIndex];
 -	weaponInfo = _vm->_dungeonMan->f158_getWeaponInfo(curThing);
 -	return ((curThing.getType() == k5_WeaponThingType) && (weaponInfo->_class == weaponClass));
 -}
 -
 -void ChampionMan::f293_drawAllChampionStates() {
 -	for (int16 i = k0_ChampionFirst; i < _g305_partyChampionCount; i++)
 -		f292_drawChampionState((ChampionIndex)i);
 -}
 -
 -void ChampionMan::f283_viAltarRebirth(uint16 champIndex) {
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	if (f285_getIndexInCell(curChampion->_cell) != kM1_ChampionNone) {
 -		uint16 numCell = k0_CellNorthWest;
 -		while (f285_getIndexInCell(numCell) != kM1_ChampionNone)
 -			numCell++;
 -
 -		curChampion->_cell = (ViewCell)numCell;
 -	}
 -
 -	uint16 maximumHealth = curChampion->_maxHealth;
 -	curChampion->_maxHealth = MAX(25, maximumHealth - (maximumHealth >> 6) - 1);
 -	curChampion->_currHealth = curChampion->_maxHealth >> 1;
 -	_vm->_menuMan->f393_drawSpellAreaControls(_g514_magicCasterChampionIndex);
 -	curChampion->_dir = _vm->_dungeonMan->_g308_partyDir;
 -	setFlag(curChampion->_attributes, k0x8000_ChampionAttributeActionHand | k0x1000_ChampionAttributeStatusBox | k0x0400_ChampionAttributeIcon);
 -	f292_drawChampionState((ChampionIndex)champIndex);
 -}
 -
 -void ChampionMan::f302_processCommands28to65_clickOnSlotBox(uint16 slotBoxIndex) {
 -	uint16 champIndex;
 -	uint16 slotIndex;
 -
 -	if (slotBoxIndex < k8_SlotBoxInventoryFirstSlot) {
 -		if (_g299_candidateChampionOrdinal)
 -			return;
 -
 -		champIndex = slotBoxIndex >> 1;
 -		if ((champIndex >= _g305_partyChampionCount) || (_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) || !_gK71_champions[champIndex]._currHealth)
 -			return;
 -
 -		slotIndex = M70_handSlotIndex(slotBoxIndex);
 -	} else {
 -		champIndex = _vm->M1_ordinalToIndex(_vm->_inventoryMan->_g432_inventoryChampionOrdinal);
 -		slotIndex = slotBoxIndex - k8_SlotBoxInventoryFirstSlot;
 -	}
 -
 -	Thing leaderHandObject = _g414_leaderHandObject;
 -	Thing slotThing;
 -	if (slotIndex >= k30_ChampionSlotChest_1) {
 -		slotThing = _vm->_inventoryMan->_g425_chestSlots[slotIndex - k30_ChampionSlotChest_1];
 -	} else {
 -		slotThing = _gK71_champions[champIndex]._slots[slotIndex];
 -	}
 -
 -	if ((slotThing == Thing::_none) && (leaderHandObject == Thing::_none))
 -		return;
 -
 -	if ((leaderHandObject != Thing::_none) && (!(g237_ObjectInfo[_vm->_dungeonMan->f141_getObjectInfoIndex(leaderHandObject)]._allowedSlots & gSlotMasks[slotIndex])))
 -		return;
 -
 -	_vm->_eventMan->f78_showMouse();
 -	if (leaderHandObject != Thing::_none)
 -		f298_getObjectRemovedFromLeaderHand();
 -
 -	if (slotThing != Thing::_none) {
 -		f300_getObjectRemovedFromSlot(champIndex, slotIndex);
 -		f297_putObjectInLeaderHand(slotThing, false);
 -	}
 -
 -	if (leaderHandObject != Thing::_none)
 -		f301_addObjectInSlot((ChampionIndex)champIndex, leaderHandObject, (ChampionSlot)slotIndex);
 -
 -	f292_drawChampionState((ChampionIndex)champIndex);
 -	_vm->_eventMan->f77_hideMouse();
 -}
 -
 -bool ChampionMan::f327_isProjectileSpellCast(uint16 champIndex, Thing thing, int16 kineticEnergy, uint16 requiredManaAmount) {
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	if (curChampion->_currMana < requiredManaAmount)
 -		return false;
 -
 -	curChampion->_currMana -= requiredManaAmount;
 -	setFlag(curChampion->_attributes, k0x0100_ChampionAttributeStatistics);
 -	int16 stepEnergy = 10 - MIN(8, curChampion->_maxMana >> 3);
 -	if (kineticEnergy < (stepEnergy << 2)) {
 -		kineticEnergy += 3;
 -		stepEnergy--;
 -	}
 -
 -	f326_championShootProjectile(curChampion, thing, kineticEnergy, 90, stepEnergy);
 -	return true; // fix BUG_01
 -}
 -
 -void ChampionMan::f326_championShootProjectile(Champion* champ, Thing thing, int16 kineticEnergy, int16 attack, int16 stepEnergy) {
 -	Direction newDirection = champ->_dir;
 -	_vm->_projexpl->f212_projectileCreate(thing, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY, M21_normalizeModulo4((((champ->_cell - newDirection + 1) & 0x0002) >> 1) + newDirection), newDirection, kineticEnergy, attack, stepEnergy);
 -	_vm->_g311_projectileDisableMovementTicks = 4;
 -	_vm->_g312_lastProjectileDisabledMovementDirection = newDirection;
 -}
 -
 -void ChampionMan::f320_applyAndDrawPendingDamageAndWounds() {
 -	Champion *championPtr = _gK71_champions;
 -	for (uint16 championIndex = k0_ChampionFirst; championIndex < _g305_partyChampionCount; championIndex++, championPtr++) {
 -		int16 pendingWounds = _g410_championPendingWounds[championIndex];
 -		setFlag(championPtr->_wounds, pendingWounds);
 -		_g410_championPendingWounds[championIndex] = 0;
 -		uint16 pendingDamage = _g409_championPendingDamage[championIndex];
 -		if (!pendingDamage)
 -			continue;
 -
 -		_g409_championPendingDamage[championIndex] = 0;
 -		int16 curHealth = championPtr->_currHealth;
 -		if (!curHealth)
 -			continue;
 -
 -		curHealth -= pendingDamage;
 -		if (curHealth <= 0) {
 -			f319_championKill(championIndex);
 -		} else {
 -			championPtr->_currHealth = curHealth;
 -			setFlag(championPtr->_attributes, k0x0100_ChampionAttributeStatistics);
 -			if (pendingWounds) {
 -				setFlag(championPtr->_attributes, k0x2000_ChampionAttributeWounds);
 -			}
 -
 -			int16 textPosX = championIndex * k69_ChampionStatusBoxSpacing;
 -			int16 textPosY;
 -
 -			Box blitBox;
 -			blitBox._y1 = 0;
 -			_vm->_eventMan->f78_showMouse();
 -
 -			if (_vm->M0_indexToOrdinal(championIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) {
 -				blitBox._y2 = 28;
 -				blitBox._x1 = textPosX + 7;
 -				blitBox._x2 = blitBox._x1 + 31; /* Box is over the champion portrait in the status box */
 -				_vm->_displayMan->f21_blitToScreen(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k16_damageToChampionBig), &blitBox, k16_byteWidth, k10_ColorFlesh, 29);
 -				// Check the number of digits and sets the position accordingly.
 -				if (pendingDamage < 10) // 1 digit
 -					textPosX += 21;
 -				else if (pendingDamage < 100)  // 2 digits
 -					textPosX += 18;
 -				else // 3 digits
 -					textPosX += 15;
 -
 -				textPosY = 16;
 -			} else {
 -				blitBox._y2 = 6;
 -				blitBox._x1 = textPosX;
 -				blitBox._x2 = blitBox._x1 + 47; /* Box is over the champion name in the status box */
 -				_vm->_displayMan->f21_blitToScreen(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k15_damageToChampionSmallIndice), &blitBox, k24_byteWidth, k10_ColorFlesh, 7);
 -				// Check the number of digits and sets the position accordingly.
 -				if (pendingDamage < 10) // 1 digit
 -					textPosX += 19;
 -				else if (pendingDamage < 100) // 2 digits
 -					textPosX += 16;
 -				else //3 digits
 -					textPosX += 13;
 -
 -				textPosY = 5;
 -			}
 -			_vm->_textMan->f53_printToLogicalScreen(textPosX, textPosY, k15_ColorWhite, k8_ColorRed, f288_getStringFromInteger(pendingDamage, false, 3).c_str());
 -
 -			int16 eventIndex = championPtr->_hideDamageReceivedIndex;
 -			if (eventIndex == -1) {
 -				TimelineEvent newEvent;
 -				newEvent._type = k12_TMEventTypeHideDamageReceived;
 -				M33_setMapAndTime(newEvent._mapTime, _vm->_dungeonMan->_g309_partyMapIndex, _vm->_g313_gameTime + 5);
 -				newEvent._priority = championIndex;
 -				championPtr->_hideDamageReceivedIndex = _vm->_timeline->f238_addEventGetEventIndex(&newEvent);
 -			} else {
 -				TimelineEvent *curEvent = &_vm->_timeline->_g370_events[eventIndex];
 -				M33_setMapAndTime(curEvent->_mapTime, _vm->_dungeonMan->_g309_partyMapIndex, _vm->_g313_gameTime + 5);
 -				_vm->_timeline->f236_fixChronology(_vm->_timeline->f235_getIndex(eventIndex));
 -			}
 -			f292_drawChampionState((ChampionIndex)championIndex);
 -			_vm->_eventMan->f77_hideMouse();
 -		}
 -	}
 -}
 -
 -void ChampionMan::f319_championKill(uint16 champIndex) {
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	curChampion->_currHealth = 0;
 -	setFlag(curChampion->_attributes, k0x1000_ChampionAttributeStatusBox);
 -	if (_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) {
 -		if (_vm->_g331_pressingEye) {
 -			_vm->_g331_pressingEye = false;
 -			_vm->_eventMan->_g597_ignoreMouseMovements = false;
 -			if (!_g415_leaderEmptyHanded) {
 -				_vm->_objectMan->f34_drawLeaderObjectName(_g414_leaderHandObject);
 -			}
 -			_vm->_eventMan->_g587_hideMousePointerRequestCount = 1;
 -			_vm->_eventMan->f77_hideMouse();
 -		} else if (_vm->_g333_pressingMouth) {
 -			_vm->_g333_pressingMouth = false;
 -			_vm->_eventMan->_g597_ignoreMouseMovements = false;
 -			_vm->_eventMan->_g587_hideMousePointerRequestCount = 1;
 -			_vm->_eventMan->f77_hideMouse();
 -		}
 -		_vm->_inventoryMan->f355_toggleInventory(k4_ChampionCloseInventory);
 -	}
 -	f318_dropAllObjects(champIndex);
 -	Thing unusedThing = _vm->_dungeonMan->f166_getUnusedThing(k0x8000_championBones | k10_JunkThingType);
 -	uint16 curCell = 0;
 -	if (unusedThing != Thing::_none) {
 -		Junk *L0966_ps_Junk = (Junk *)_vm->_dungeonMan->f156_getThingData(unusedThing);
 -		L0966_ps_Junk->setType(k5_JunkTypeBones);
 -		L0966_ps_Junk->setDoNotDiscard(true);
 -		L0966_ps_Junk->setChargeCount(champIndex);
 -		curCell = curChampion->_cell;
 -		_vm->_moveSens->f267_getMoveResult(M15_thingWithNewCell(unusedThing, curCell), kM1_MapXNotOnASquare, 0, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY);
 -	}
 -	curChampion->_symbolStep = 0;
 -	curChampion->_symbols[0] = '\0';
 -	curChampion->_dir = _vm->_dungeonMan->_g308_partyDir;
 -	curChampion->_maximumDamageReceived = 0;
 -	uint16 curChampionIconIndex = M26_championIconIndex(curCell, _vm->_dungeonMan->_g308_partyDir);
 -	if (_vm->M0_indexToOrdinal(curChampionIconIndex) == _vm->_eventMan->_g599_useChampionIconOrdinalAsMousePointerBitmap) {
 -		_vm->_eventMan->_g598_mousePointerBitmapUpdated = true;
 -		_vm->_eventMan->_g599_useChampionIconOrdinalAsMousePointerBitmap = _vm->M0_indexToOrdinal(kM1_ChampionNone);
 -		warning(false, "IGNORED CODE:G0592_B_BuildMousePointerScreenAreaRequested = true");
 -	}
 -
 -	if (curChampion->_poisonEventCount)
 -		f323_unpoison(champIndex);
 -
 -	_vm->_displayMan->_g578_useByteBoxCoordinates = false;
 -	_vm->_displayMan->D24_fillScreenBox(g54_BoxChampionIcons[curChampionIconIndex << 2], k0_ColorBlack);
 -	f292_drawChampionState((ChampionIndex)champIndex);
 -
 -	int16 aliveChampionIndex;
 -	for (aliveChampionIndex = k0_ChampionFirst, curChampion = _gK71_champions; aliveChampionIndex < _g305_partyChampionCount; aliveChampionIndex++, curChampion++) {
 -		if (curChampion->_currHealth)
 -			break;
 -	}
 -
 -	if (aliveChampionIndex == _g305_partyChampionCount) { /* BUG0_43 The game does not end if the last living champion in the party is killed while looking at a candidate champion in a portrait. The condition to end the game when the whole party is killed is not true because the code considers the candidate champion as alive (in the loop above) */
 -		_g303_partyDead = true;
 -		return;
 -	}
 -
 -	if (champIndex == _g411_leaderIndex)
 -		_vm->_eventMan->f368_commandSetLeader((ChampionIndex)aliveChampionIndex);
 -
 -	if (champIndex == _g514_magicCasterChampionIndex)
 -		_vm->_menuMan->f394_setMagicCasterAndDrawSpellArea(aliveChampionIndex);
 -	else
 -		_vm->_menuMan->f393_drawSpellAreaControls(_g514_magicCasterChampionIndex);
 -}
 -
 -void ChampionMan::f318_dropAllObjects(uint16 champIndex) {
 -	static const int16 slotDropOrder[30] = {
 -		k5_ChampionSlotFeet,
 -		k4_ChampionSlotLegs,
 -		k9_ChampionSlotQuiverLine_2_2,
 -		k8_ChampionSlotQuiverLine_1_2,
 -		k7_ChampionSlotQuiverLine_2_1,
 -		k12_ChampionSlotQuiverLine_1_1,
 -		k6_ChampionSlotPouch_2,
 -		k11_ChampionSlotPouch_1,
 -		k3_ChampionSlotTorso,
 -		k13_ChampionSlotBackpackLine_1_1,
 -		k14_ChampionSlotBackpackLine_2_2,
 -		k15_ChampionSlotBackpackLine_2_3,
 -		k16_ChampionSlotBackpackLine_2_4,
 -		k17_ChampionSlotBackpackLine_2_5,
 -		k18_ChampionSlotBackpackLine_2_6,
 -		k19_ChampionSlotBackpackLine_2_7,
 -		k20_ChampionSlotBackpackLine_2_8,
 -		k21_ChampionSlotBackpackLine_2_9,
 -		k22_ChampionSlotBackpackLine_1_2,
 -		k23_ChampionSlotBackpackLine_1_3,
 -		k24_ChampionSlotBackpackLine_1_4,
 -		k25_ChampionSlotBackpackLine_1_5,
 -		k26_ChampionSlotBackpackLine_1_6,
 -		k27_ChampionSlotBackpackLine_1_7,
 -		k28_ChampionSlotBackpackLine_1_8,
 -		k29_ChampionSlotBackpackLine_1_9,
 -		k10_ChampionSlotNeck,
 -		k2_ChampionSlotHead,
 -		k0_ChampionSlotReadyHand,
 -		k1_ChampionSlotActionHand
 -	};
 -
 -	uint16 curCell = _gK71_champions[champIndex]._cell;
 -	for (uint16 slotIndex = k0_ChampionSlotReadyHand; slotIndex < k30_ChampionSlotChest_1; slotIndex++) {
 -		Thing curThing = f300_getObjectRemovedFromSlot(champIndex, slotDropOrder[slotIndex]);
 -		if (curThing != Thing::_none)
 -			_vm->_moveSens->f267_getMoveResult(M15_thingWithNewCell(curThing, curCell), kM1_MapXNotOnASquare, 0, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY);
 -	}
 -}
 -
 -void ChampionMan::f323_unpoison(int16 champIndex) {
 -	if (champIndex == kM1_ChampionNone)
 -		return;
 -
 -	TimelineEvent *eventPtr = _vm->_timeline->_g370_events;
 -	for (uint16 eventIndex = 0; eventIndex < _vm->_timeline->_g369_eventMaxCount; eventPtr++, eventIndex++) {
 -		if ((eventPtr->_type == k75_TMEventTypePoisonChampion) && (eventPtr->_priority == champIndex))
 -			_vm->_timeline->f237_deleteEvent(eventIndex);
 -	}
 -	_gK71_champions[champIndex]._poisonEventCount = 0;
 -}
 -
 -void ChampionMan::f331_applyTimeEffects() {
 -	if (!_g305_partyChampionCount)
 -		return;
 -
 -	Scent checkScent;
 -	checkScent.setMapX(_vm->_dungeonMan->_g306_partyMapX);
 -	checkScent.setMapY(_vm->_dungeonMan->_g307_partyMapY);
 -	checkScent.setMapIndex(_vm->_dungeonMan->_g309_partyMapIndex);
 -
 -	for (byte loopScentIndex = 0; loopScentIndex + 1 < _g407_party._scentCount; loopScentIndex++) {
 -		if (&_g407_party._scents[loopScentIndex] != &checkScent) {
 -			_g407_party._scentStrengths[loopScentIndex] = MAX(0, _g407_party._scentStrengths[loopScentIndex] - 1);
 -			if (!_g407_party._scentStrengths[loopScentIndex] && !loopScentIndex) {
 -				f316_deleteScent(0);
 -				continue;
 -			}
 -		}
 -	}
 -
 -	uint16 gameTime = _vm->_g313_gameTime & 0xFFFF;
 -	uint16 timeCriteria = (((gameTime & 0x0080) + ((gameTime & 0x0100) >> 2)) + ((gameTime & 0x0040) << 2)) >> 2;
 -	Champion *championPtr = _gK71_champions;
 -	for (uint16 championIndex = k0_ChampionFirst; championIndex < _g305_partyChampionCount; championIndex++, championPtr++) {
 -		if (championPtr->_currHealth && (_vm->M0_indexToOrdinal(championIndex) != _g299_candidateChampionOrdinal)) {
 -			uint16 wizardSkillLevel = f303_getSkillLevel(championIndex, k3_ChampionSkillWizard) + f303_getSkillLevel(championIndex, k2_ChampionSkillPriest);
 -			if ((championPtr->_currMana < championPtr->_maxMana)
 -				&& (timeCriteria < championPtr->_statistics[k3_ChampionStatWisdom][k1_ChampionStatCurrent] + wizardSkillLevel)) {
 -				int16 manaGain = championPtr->_maxMana / 40;
 -				if (_g300_partyIsSleeping)
 -					manaGain <<= 1;
 -
 -				manaGain++;
 -				f325_decrementStamina(championIndex, manaGain * MAX(7, 16 - wizardSkillLevel));
 -				championPtr->_currMana += MIN<int16>(manaGain, championPtr->_maxMana - championPtr->_currMana);
 -			} else if (championPtr->_currMana > championPtr->_maxMana)
 -				championPtr->_currMana--;
 -
 -			for (int16 idx = k19_ChampionSkillWater; idx >= k0_ChampionSkillFighter; idx--) {
 -				if (championPtr->_skills[idx]._temporaryExperience > 0)
 -					championPtr->_skills[idx]._temporaryExperience--;
 -			}
 -			uint16 staminaGainCycleCount = 4;
 -			int16 staminaMagnitude = championPtr->_maxStamina;
 -			while (championPtr->_currStamina < (staminaMagnitude >>= 1))
 -				staminaGainCycleCount += 2;
 -
 -			int16 staminaLoss = 0;
 -			int16 staminaAmount = f26_getBoundedValue(1, (championPtr->_maxStamina >> 8) - 1, 6);
 -			if (_g300_partyIsSleeping)
 -				staminaAmount <<= 1;
 -
 -			int32 compDelay = _vm->_g313_gameTime - _vm->_projexpl->_g362_lastPartyMovementTime;
 -			if (compDelay > 80) {
 -				staminaAmount++;
 -				if (compDelay > 250)
 -					staminaAmount++;
 -			}
 -			do {
 -				bool staminaAboveHalf = (staminaGainCycleCount <= 4);
 -				if (championPtr->_food < -512) {
 -					if (staminaAboveHalf) {
 -						staminaLoss += staminaAmount;
 -						championPtr->_food -= 2;
 -					}
 -				} else {
 -					if (championPtr->_food >= 0)
 -						staminaLoss -= staminaAmount;
 -
 -					championPtr->_food -= staminaAboveHalf ? 2 : staminaGainCycleCount >> 1;
 -				}
 -				if (championPtr->_water < -512) {
 -					if (staminaAboveHalf) {
 -						staminaLoss += staminaAmount;
 -						championPtr->_water -= 1;
 -					}
 -				} else {
 -					if (championPtr->_water >= 0)
 -						staminaLoss -= staminaAmount;
 -
 -					championPtr->_water -= staminaAboveHalf ? 1 : staminaGainCycleCount >> 2;
 -				}
 -			} while (--staminaGainCycleCount && ((championPtr->_currStamina - staminaLoss) < championPtr->_maxStamina));
 -			f325_decrementStamina(championIndex, staminaLoss);
 -			if (championPtr->_food < -1024)
 -				championPtr->_food = -1024;
 -
 -			if (championPtr->_water < -1024)
 -				championPtr->_water = -1024;
 -
 -			if ((championPtr->_currHealth < championPtr->_maxHealth) && (championPtr->_currStamina >= (championPtr->_maxStamina >> 2)) && (timeCriteria < (championPtr->_statistics[k4_ChampionStatVitality][k1_ChampionStatCurrent] + 12))) {
 -				int16 healthGain = (championPtr->_maxHealth >> 7) + 1;
 -				if (_g300_partyIsSleeping)
 -					healthGain <<= 1;
 -
 -				if (_vm->_objectMan->f33_getIconIndex(championPtr->_slots[k10_ChampionSlotNeck]) == k121_IconIndiceJunkEkkhardCross)
 -					healthGain += (healthGain >> 1) + 1;
 -
 -				championPtr->_currHealth += MIN(healthGain, (int16)(championPtr->_maxHealth - championPtr->_currHealth));
 -			}
 -			if (!((int)_vm->_g313_gameTime & (_g300_partyIsSleeping ? 63 : 255))) {
 -				for (uint16 i = k0_ChampionStatLuck; i <= k6_ChampionStatAntifire; i++) {
 -					byte *curStatistic = championPtr->_statistics[i];
 -					uint16 statisticMaximum = curStatistic[k0_ChampionStatMaximum];
 -					if (curStatistic[k1_ChampionStatCurrent] < statisticMaximum)
 -						curStatistic[k1_ChampionStatCurrent]++;
 -					else if (curStatistic[k1_ChampionStatCurrent] > statisticMaximum)
 -						curStatistic[k1_ChampionStatCurrent] -= curStatistic[k1_ChampionStatCurrent] / statisticMaximum;
 -				}
 -			}
 -			if (!_g300_partyIsSleeping && (championPtr->_dir != _vm->_dungeonMan->_g308_partyDir) && (_vm->_projexpl->_g361_lastCreatureAttackTime + 60 < _vm->_g313_gameTime)) {
 -				championPtr->_dir = _vm->_dungeonMan->_g308_partyDir;
 -				championPtr->_maximumDamageReceived = 0;
 -				setFlag(championPtr->_attributes, k0x0400_ChampionAttributeIcon);
 -			}
 -			setFlag(championPtr->_attributes, k0x0100_ChampionAttributeStatistics);
 -			if (_vm->M0_indexToOrdinal(championIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) {
 -				if (_vm->_g333_pressingMouth || _vm->_g331_pressingEye || (_vm->_inventoryMan->_g424_panelContent == k0_PanelContentFoodWaterPoisoned)) {
 -					setFlag(championPtr->_attributes, k0x0800_ChampionAttributePanel);
 -				}
 -			}
 -		}
 -	}
 -	f293_drawAllChampionStates();
 -}
 -
 -void ChampionMan::save2_PartyPart(Common::OutSaveFile* file) {
 -	for (uint16 i = 0; i < 4; ++i) {
 -		Champion *champ = &_gK71_champions[i];
 -		file->writeUint16BE(champ->_attributes);
 -		file->writeUint16BE(champ->_wounds);
 -		for (uint16 y = 0; y < 7; ++y)
 -			for (uint16 x = 0; x < 3; ++x)
 -				file->writeByte(champ->_statistics[y][x]);
 -		for (uint16 j = 0; j < 30; ++j)
 -			file->writeUint16BE(champ->_slots[j].toUint16());
 -		for (uint16 j = 0; j < 20; ++j) {
 -			file->writeSint16BE(champ->_skills[j]._temporaryExperience);
 -			file->writeSint32BE(champ->_skills[j]._experience);
 -		}
 -		for (uint16 j = 0; j < 8; ++j)
 -			file->writeByte(champ->_name[j]);
 -		for (uint16 j = 0; j < 20; ++j)
 -			file->writeByte(champ->_title[j]);
 -		file->writeUint16BE(champ->_dir);
 -		file->writeUint16BE(champ->_cell);
 -		file->writeUint16BE(champ->_actionIndex);
 -		file->writeUint16BE(champ->_symbolStep);
 -		for (uint16 j = 0; j < 5; ++j)
 -			file->writeByte(champ->_symbols[j]);
 -		file->writeUint16BE(champ->_directionMaximumDamageReceived);
 -		file->writeUint16BE(champ->_maximumDamageReceived);
 -		file->writeUint16BE(champ->_poisonEventCount);
 -		file->writeSint16BE(champ->_enableActionEventIndex);
 -		file->writeSint16BE(champ->_hideDamageReceivedIndex);
 -		file->writeSint16BE(champ->_currHealth);
 -		file->writeSint16BE(champ->_maxHealth);
 -		file->writeSint16BE(champ->_currStamina);
 -		file->writeSint16BE(champ->_maxStamina);
 -		file->writeSint16BE(champ->_currMana);
 -		file->writeSint16BE(champ->_maxMana);
 -		file->writeSint16BE(champ->_actionDefense);
 -		file->writeSint16BE(champ->_food);
 -		file->writeSint16BE(champ->_water);
 -		file->writeUint16BE(champ->_load);
 -		file->writeSint16BE(champ->_shieldDefense);
 -		for (uint16 j = 0; j < 928; ++j)
 -			file->writeByte(champ->_portrait[j]);
 -	}
 -
 -	Party &party = _g407_party;
 -	file->writeSint16BE(party._magicalLightAmount);
 -	file->writeByte(party._event73Count_ThievesEye);
 -	file->writeByte(party._event79Count_Footprints);
 -	file->writeSint16BE(party._shieldDefense);
 -	file->writeSint16BE(party._fireShieldDefense);
 -	file->writeSint16BE(party._spellShieldDefense);
 -	file->writeByte(party._scentCount);
 -	file->writeByte(party._freezeLifeTicks);
 -	file->writeByte(party._firstScentIndex);
 -	file->writeByte(party._lastScentIndex);
 -	for (uint16 i = 0; i < 24; ++i)
 -		file->writeUint16BE(party._scents[i].toUint16());
 -	for (uint16 i = 0; i < 24; ++i)
 -		file->writeByte(party._scentStrengths[i]);
 -	file->writeByte(party._event71Count_Invisibility);
 -}
 -
 -void ChampionMan::load2_PartyPart(Common::InSaveFile* file) {
 -	for (uint16 i = 0; i < 4; ++i) {
 -		Champion *champ = &_gK71_champions[i];
 -		champ->_attributes = file->readUint16BE();
 -		champ->_wounds = file->readUint16BE();
 -		for (uint16 y = 0; y < 7; ++y)
 -			for (uint16 x = 0; x < 3; ++x)
 -				champ->_statistics[y][x] = file->readByte();
 -		for (uint16 j = 0; j < 30; ++j)
 -			champ->_slots[j] = Thing(file->readUint16BE());
 -		for (uint16 j = 0; j < 20; ++j) {
 -			champ->_skills[j]._temporaryExperience = file->readSint16BE();
 -			champ->_skills[j]._experience = file->readSint32BE();
 -		}
 -		for (uint16 j = 0; j < 8; ++j)
 -			champ->_name[j] = file->readByte();
 -		for (uint16 j = 0; j < 20; ++j)
 -			champ->_title[j] = file->readByte();
 -		champ->_dir = (Direction)file->readUint16BE();
 -		champ->_cell = (ViewCell)file->readUint16BE();
 -		champ->_actionIndex = (ChampionAction)file->readUint16BE();
 -		champ->_symbolStep = file->readUint16BE();
 -		for (uint16 j = 0; j < 5; ++j)
 -			champ->_symbols[j] = file->readByte();
 -		champ->_directionMaximumDamageReceived = file->readUint16BE();
 -		champ->_maximumDamageReceived = file->readUint16BE();
 -		champ->_poisonEventCount = file->readUint16BE();
 -		champ->_enableActionEventIndex = file->readSint16BE();
 -		champ->_hideDamageReceivedIndex = file->readSint16BE();
 -		champ->_currHealth = file->readSint16BE();
 -		champ->_maxHealth = file->readSint16BE();
 -		champ->_currStamina = file->readSint16BE();
 -		champ->_maxStamina = file->readSint16BE();
 -		champ->_currMana = file->readSint16BE();
 -		champ->_maxMana = file->readSint16BE();
 -		champ->_actionDefense = file->readSint16BE();
 -		champ->_food = file->readSint16BE();
 -		champ->_water = file->readSint16BE();
 -		champ->_load = file->readUint16BE();
 -		champ->_shieldDefense = file->readSint16BE();
 -		for (uint16 j = 0; j < 928; ++j)
 -			champ->_portrait[j] = file->readByte();
 -	}
 -
 -	Party &party = _g407_party;
 -	party._magicalLightAmount = file->readSint16BE();
 -	party._event73Count_ThievesEye = file->readByte();
 -	party._event79Count_Footprints = file->readByte();
 -	party._shieldDefense = file->readSint16BE();
 -	party._fireShieldDefense = file->readSint16BE();
 -	party._spellShieldDefense = file->readSint16BE();
 -	party._scentCount = file->readByte();
 -	party._freezeLifeTicks = file->readByte();
 -	party._firstScentIndex = file->readByte();
 -	party._lastScentIndex = file->readByte();
 -	for (uint16 i = 0; i < 24; ++i)
 -		party._scents[i] = Scent(file->readUint16BE());
 -	for (uint16 i = 0; i < 24; ++i)
 -		party._scentStrengths[i] = file->readByte();
 -	party._event71Count_Invisibility = file->readByte();
 -}
 -
 -ChampionIndex ChampionMan::f285_getIndexInCell(int16 cell) {
 -	for (uint16 i = 0; i < _g305_partyChampionCount; ++i) {
 -		if ((_gK71_champions[i]._cell == cell) && _gK71_champions[i]._currHealth)
 -			return (ChampionIndex)i;
 -	}
 -
 -	return kM1_ChampionNone;
 -}
 -
 -void ChampionMan::f278_resetDataToStartGame() {
 -	if (!_vm->_g298_newGame) {
 -		Thing L0787_T_Thing;
 -		if ((L0787_T_Thing = _g414_leaderHandObject) == Thing::_none) {
 -			_g415_leaderEmptyHanded = true;
 -			_g413_leaderHandObjectIconIndex = kM1_IconIndiceNone;
 -			_vm->_eventMan->f69_setMousePointer();
 -		} else {
 -			f297_putObjectInLeaderHand(L0787_T_Thing, true); /* This call will add the weight of the leader hand object to the Load of the leader a first time */
 -		}
 -		Champion *L0788_ps_Champion = _gK71_champions;
 -		int16 L0785_i_ChampionIndex;
 -		for (L0785_i_ChampionIndex = k0_ChampionFirst; L0785_i_ChampionIndex < _g305_partyChampionCount; L0785_i_ChampionIndex++, L0788_ps_Champion++) {
 -			clearFlag(L0788_ps_Champion->_attributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand);
 -			setFlag(L0788_ps_Champion->_attributes, k0x8000_ChampionAttributeActionHand | k0x1000_ChampionAttributeStatusBox | k0x0400_ChampionAttributeIcon);
 -		}
 -		f293_drawAllChampionStates();
 -		if ((L0785_i_ChampionIndex = _g411_leaderIndex) != kM1_ChampionNone) {
 -			_g411_leaderIndex = kM1_ChampionNone;
 -			_vm->_eventMan->f368_commandSetLeader((ChampionIndex)L0785_i_ChampionIndex);
 -		}
 -		if ((L0785_i_ChampionIndex = _g514_magicCasterChampionIndex) != kM1_ChampionNone) {
 -			_g514_magicCasterChampionIndex = kM1_ChampionNone;
 -			_vm->_menuMan->f394_setMagicCasterAndDrawSpellArea(L0785_i_ChampionIndex);
 -		}
 -		return;
 -	}
 -
 -	_g414_leaderHandObject = Thing::_none;
 -	_g413_leaderHandObjectIconIndex = kM1_IconIndiceNone;
 -	_g415_leaderEmptyHanded = true;
 -}
 -
 -void ChampionMan::f280_addCandidateChampionToParty(uint16 championPortraitIndex) {
 -	if (!_g415_leaderEmptyHanded)
 -		return;
 -
 -	if (_g305_partyChampionCount == 4)
 -		return;
 -
 -	uint16 previousPartyChampionCount = _g305_partyChampionCount;
 -	Champion *championPtr = &_gK71_champions[previousPartyChampionCount];
 -	championPtr->resetToZero();
 -	// Strangerke - TODO: Check if the new code is possible to run on the older version (example: the portraits could be missing in the data)
 -	_vm->_displayMan->_g578_useByteBoxCoordinates = true;
 -	_vm->_displayMan->f132_blitToBitmap(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k26_ChampionPortraitsIndice), championPtr->_portrait, gBoxChampionPortrait, M27_getChampionPortraitX(championPortraitIndex), M28_getChampionPortraitY(championPortraitIndex), k128_byteWidth, k16_byteWidth, kM1_ColorNoTransparency);
 -	championPtr->_actionIndex = k255_ChampionActionNone;
 -	championPtr->_enableActionEventIndex = -1;
 -	championPtr->_hideDamageReceivedIndex = -1;
 -	championPtr->_dir = _vm->_dungeonMan->_g308_partyDir;
 -	uint16 viewCell = k0_ViewCellFronLeft;
 -	while (f285_getIndexInCell(M21_normalizeModulo4(viewCell + _vm->_dungeonMan->_g308_partyDir)) != kM1_ChampionNone)
 -		viewCell++;
 -
 -	championPtr->_cell = (ViewCell)M21_normalizeModulo4(viewCell + _vm->_dungeonMan->_g308_partyDir);
 -	championPtr->_attributes = k0x0400_ChampionAttributeIcon;
 -	championPtr->_directionMaximumDamageReceived = _vm->_dungeonMan->_g308_partyDir;
 -	championPtr->_food = 1500 + _vm->getRandomNumber(256);
 -	championPtr->_water = 1500 + _vm->getRandomNumber(256);
 -	for (int16 slotIdx = k0_ChampionSlotReadyHand; slotIdx < k30_ChampionSlotChest_1; slotIdx++)
 -		championPtr->_slots[slotIdx] = Thing::_none;
 -
 -	Thing curThing = _vm->_dungeonMan->f161_getSquareFirstThing(_vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY);
 -	while (curThing.getType() != k2_TextstringType)
 -		curThing = _vm->_dungeonMan->f159_getNextThing(curThing);
 -
 -	char L0807_ac_DecodedChampionText[77];
 -	char *decodedStringPtr = L0807_ac_DecodedChampionText;
 -	_vm->_dungeonMan->f168_decodeText(decodedStringPtr, curThing, (TextType)(k2_TextTypeScroll | k0x8000_DecodeEvenIfInvisible));
 -
 -	uint16 charIdx = 0;
 -	char tmpChar;
 -	while ((tmpChar = *decodedStringPtr++) != '\n')
 -		championPtr->_name[charIdx++] = tmpChar;
 -
 -	championPtr->_name[charIdx] = '\0';
 -	charIdx = 0;
 -	bool championTitleCopiedFl = false;
 -	for (;;) { /*_Infinite loop_*/
 -		tmpChar = *decodedStringPtr++;
 -		if (tmpChar == '\n') { /* New line */
 -			if (championTitleCopiedFl)
 -				break;
 -			championTitleCopiedFl = true;
 -		} else
 -			championPtr->_title[charIdx++] = tmpChar;
 -	}
 -	championPtr->_title[charIdx] = '\0';
 -	if (*decodedStringPtr++ == 'M')
 -		setFlag(championPtr->_attributes, k0x0010_ChampionAttributeMale);
 -
 -	decodedStringPtr++;
 -	championPtr->_currHealth = championPtr->_maxHealth = f279_getDecodedValue(decodedStringPtr, 4);
 -	decodedStringPtr += 4;
 -	championPtr->_currStamina = championPtr->_maxStamina = f279_getDecodedValue(decodedStringPtr, 4);
 -	decodedStringPtr += 4;
 -	championPtr->_currMana = championPtr->_maxMana = f279_getDecodedValue(decodedStringPtr, 4);
 -	decodedStringPtr += 4;
 -	decodedStringPtr++;
 -	for (int16 statIdx = k0_ChampionStatLuck; statIdx <= k6_ChampionStatAntifire; statIdx++) {
 -		championPtr->_statistics[statIdx][k2_ChampionStatMinimum] = 30;
 -		championPtr->_statistics[statIdx][k1_ChampionStatCurrent] = championPtr->_statistics[statIdx][k0_ChampionStatMaximum] = f279_getDecodedValue(decodedStringPtr, 2);
 -		decodedStringPtr += 2;
 -	}
 -	championPtr->_statistics[k0_ChampionStatLuck][k2_ChampionStatMinimum] = 10;
 -	decodedStringPtr++;
 -	for (uint16 skillIdx = k4_ChampionSkillSwing; skillIdx <= k19_ChampionSkillWater; skillIdx++) {
 -		int skillValue = *decodedStringPtr++ - 'A';
 -		if (skillValue > 0)
 -			championPtr->_skills[skillIdx]._experience = 125L << skillValue;
 -	}
 -	for (uint16 skillIdx = k0_ChampionSkillFighter; skillIdx <= k3_ChampionSkillWizard; skillIdx++) {
 -		int32 baseSkillExperience = 0;
 -		int16 hiddenSkillIndex = (skillIdx + 1) << 2;
 -		for (uint16 hiddenIdx = 0; hiddenIdx < 4; hiddenIdx++)
 -			baseSkillExperience += championPtr->_skills[hiddenSkillIndex + hiddenIdx]._experience;
 -
 -		championPtr->_skills[skillIdx]._experience = baseSkillExperience;
 -	}
 -	_g299_candidateChampionOrdinal = previousPartyChampionCount + 1;
 -	if (++_g305_partyChampionCount == 1) {
 -		_vm->_eventMan->f368_commandSetLeader(k0_ChampionFirst);
 -		_vm->_menuMan->_g508_refreshActionArea = true;
 -	} else {
 -		_vm->_menuMan->f388_clearActingChampion();
 -		_vm->_menuMan->f386_drawActionIcon((ChampionIndex)(_g305_partyChampionCount - 1));
 -	}
 -
 -	int16 curMapX = _vm->_dungeonMan->_g306_partyMapX;
 -	int16 curMapY = _vm->_dungeonMan->_g307_partyMapY;
 -	uint16 championObjectsCell = returnOppositeDir(_vm->_dungeonMan->_g308_partyDir);
 -	curMapX += _vm->_dirIntoStepCountEast[_vm->_dungeonMan->_g308_partyDir], curMapY += _vm->_dirIntoStepCountNorth[_vm->_dungeonMan->_g308_partyDir];
 -	curThing = _vm->_dungeonMan->f161_getSquareFirstThing(curMapX, curMapY);
 -	int16 slotIdx = k13_ChampionSlotBackpackLine_1_1;
 -	while (curThing != Thing::_endOfList) {
 -		ThingType thingType = curThing.getType();
 -		if ((thingType > k3_SensorThingType) && (curThing.getCell() == championObjectsCell)) {
 -			int16 objectAllowedSlots = g237_ObjectInfo[_vm->_dungeonMan->f141_getObjectInfoIndex(curThing)]._allowedSlots;
 -			uint16 curSlotIndex;
 -			switch (thingType) {
 -			case k6_ArmourThingType: {
 -				bool skipCheck = false;
 -				for (curSlotIndex = k2_ChampionSlotHead; curSlotIndex <= k5_ChampionSlotFeet; curSlotIndex++) {
 -					if (objectAllowedSlots & gSlotMasks[curSlotIndex]) {
 -						skipCheck = true;
 -						break;
 -					}
 -				}
 -
 -				if (skipCheck)
 -					break;
 -
 -				if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none))
 -					curSlotIndex = k10_ChampionSlotNeck;
 -				else
 -					curSlotIndex = slotIdx++;
 -
 -				break;
 -			}
 -			case k5_WeaponThingType:
 -				if (championPtr->_slots[k1_ChampionSlotActionHand] == Thing::_none)
 -					curSlotIndex = k1_ChampionSlotActionHand;
 -				else if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none))
 -					curSlotIndex = k10_ChampionSlotNeck;
 -				else
 -					curSlotIndex = slotIdx++;
 -				break;
 -			case k7_ScrollThingType:
 -			case k8_PotionThingType:
 -				if (championPtr->_slots[k11_ChampionSlotPouch_1] == Thing::_none)
 -					curSlotIndex = k11_ChampionSlotPouch_1;
 -				else if (championPtr->_slots[k6_ChampionSlotPouch_2] == Thing::_none)
 -					curSlotIndex = k6_ChampionSlotPouch_2;
 -				else if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none))
 -					curSlotIndex = k10_ChampionSlotNeck;
 -				else
 -					curSlotIndex = slotIdx++;
 -				break;
 -			case k9_ContainerThingType:
 -			case k10_JunkThingType:
 -				if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none))
 -					curSlotIndex = k10_ChampionSlotNeck;
 -				else
 -					curSlotIndex = slotIdx++;
 -
 -				break;
 -			default:
 -				break;
 -			}
 -
 -			while (championPtr->_slots[curSlotIndex] != Thing::_none) {
 -				if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none))
 -					curSlotIndex = k10_ChampionSlotNeck;
 -				else
 -					curSlotIndex = slotIdx++;
 -			}
 -			f301_addObjectInSlot((ChampionIndex)previousPartyChampionCount, curThing, (ChampionSlot)curSlotIndex);
 -		}
 -		curThing = _vm->_dungeonMan->f159_getNextThing(curThing);
 -	}
 -	_vm->_inventoryMan->f355_toggleInventory((ChampionIndex)previousPartyChampionCount);
 -	_vm->_menuMan->f456_drawDisabledMenu();;
 -}
 -
 -void ChampionMan::f287_drawChampionBarGraphs(ChampionIndex champIndex) {
 -	int16 barGraphHeights[3];
 -	Champion *champ = &_gK71_champions[champIndex];
 -	int16 barGraphIdx = 0;
 -	if (champ->_currHealth > 0) {
 -		int32 barGraphHeight = (((int32)champ->_currHealth << 10) * 25) / champ->_maxHealth;
 -		barGraphHeights[barGraphIdx++] = (barGraphHeight >> 10) + ((barGraphHeight & 0x000003FF) ? 1 : 0);
 -	} else
 -		barGraphHeights[barGraphIdx++] = 0;
 -
 -	if (champ->_currStamina > 0) {
 -		int32 barGraphHeight = (((int32)champ->_currStamina << 10) * 25) / champ->_maxStamina;
 -		barGraphHeights[barGraphIdx++] = (barGraphHeight >> 10) + ((barGraphHeight & 0x000003FF) ? 1 : 0);
 -	} else
 -		barGraphHeights[barGraphIdx++] = 0;
 -
 -	if (champ->_currMana > 0) {
 -		if (champ->_currMana > champ->_maxMana)
 -			barGraphHeights[barGraphIdx] = 25;
 -		else {
 -			int32 barGraphHeight = (((int32)champ->_currMana << 10) * 25) / champ->_maxMana;
 -			barGraphHeights[barGraphIdx] = (barGraphHeight >> 10) + ((barGraphHeight & 0x000003FF) ? 1 : 0);
 -		}
 -	} else {
 -		barGraphHeights[barGraphIdx] = 0;
 -	}
 -	_vm->_eventMan->f78_showMouse();
 -
 -	// Strangerke - TO CHECK: if portraits, maybe the old (assembly) code is required for older versions
 -	Box box;
 -	box._x1 = champIndex * k69_ChampionStatusBoxSpacing + 46;
 -	box._x2 = box._x1 + 3;
 -	box._y1 = 2;
 -	box._y2 = 26;
 -	for (int16 barGraphIndex = 0; barGraphIndex < 3; barGraphIndex++) {
 -		int16 barGraphHeight = barGraphHeights[barGraphIndex];
 -		if (barGraphHeight < 25) {
 -			box._y1 = 2;
 -			box._y2 = 27 - barGraphHeight;
 -			_vm->_displayMan->D24_fillScreenBox(box, k12_ColorDarkestGray);
 -		}
 -		if (barGraphHeight) {
 -			box._y1 = 27 - barGraphHeight;
 -			box._y2 = 26;
 -			_vm->_displayMan->D24_fillScreenBox(box, g46_ChampionColor[champIndex]);
 -		}
 -		box._x1 += 7;
 -		box._x2 += 7;
 -	}
 -	_vm->_eventMan->f77_hideMouse();
 -}
 -
 -
 -uint16 ChampionMan::f306_getStaminaAdjustedValue(Champion *champ, int16 val) {
 -	int16 currStamina = champ->_currStamina;
 -	int16 halfMaxStamina = champ->_maxStamina / 2;
 -	if (currStamina < halfMaxStamina) {
 -		warning(false, "Possible undefined behavior in the original code");
 -		val /= 2;
 -		return val + ((uint32)val * (uint32)currStamina) / halfMaxStamina;
 -	}
 -	return val;
 -}
 -
 -uint16 ChampionMan::f309_getMaximumLoad(Champion *champ) {
 -	uint16 maximumLoad = champ->getStatistic(k1_ChampionStatStrength, k1_ChampionStatCurrent) * 8 + 100;
 -	maximumLoad = f306_getStaminaAdjustedValue(champ, maximumLoad);
 -	int16 wounds = champ->getWounds();
 -	if (wounds)
 -		maximumLoad -= maximumLoad >> (champ->getWoundsFlag(k0x0010_ChampionWoundLegs) ? 2 : 3);
 -
 -	if (_vm->_objectMan->f33_getIconIndex(champ->getSlot(k5_ChampionSlotFeet)) == k119_IconIndiceArmourElvenBoots)
 -		maximumLoad += maximumLoad * 16;
 -
 -	maximumLoad += 9;
 -	maximumLoad -= maximumLoad % 10;
 -	return maximumLoad;
 -}
 -
 -void ChampionMan::f292_drawChampionState(ChampionIndex champIndex) {
 -	int16 championStatusBoxX = champIndex * k69_ChampionStatusBoxSpacing;
 -	Champion *curChampion = &_gK71_champions[champIndex];
 -	uint16 championAttributes = curChampion->_attributes;
 -	if (!getFlag(championAttributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand))
 -		return;
 -
 -	bool isInventoryChampion = (_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal);
 -	_vm->_displayMan->_g578_useByteBoxCoordinates = false;
 -	_vm->_eventMan->f78_showMouse();
 -	if (getFlag(championAttributes, k0x1000_ChampionAttributeStatusBox)) {
 -		Box box;
 -		box._y1 = 0;
 -		box._y2 = 28;
 -		box._x1 = championStatusBoxX;
 -		box._x2 = box._x1 + 66;
 -		if (curChampion->_currHealth) {
 -			_vm->_displayMan->D24_fillScreenBox(box, k12_ColorDarkestGray);
 -			int16 nativeBitmapIndices[3];
 -			for (uint16 i = 0; i < 3; ++i)
 -				nativeBitmapIndices[i] = 0;
 -
 -			uint16 borderCount = 0;
 -			if (_g407_party._fireShieldDefense > 0)
 -				nativeBitmapIndices[borderCount++] = k38_BorderPartyFireshieldIndice;
 -
 -			if (_g407_party._spellShieldDefense > 0)
 -				nativeBitmapIndices[borderCount++] = k39_BorderPartySpellshieldIndice;
 -
 -			if ((_g407_party._shieldDefense > 0) || curChampion->_shieldDefense)
 -				nativeBitmapIndices[borderCount++] = k37_BorderPartyShieldIndice;
 -
 -			while (borderCount--)
 -				_vm->_displayMan->f21_blitToScreen(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndices[borderCount]), &box, k40_byteWidth, k10_ColorFlesh, 29);
 -
 -			if (isInventoryChampion) {
 -				_vm->_inventoryMan->f354_drawStatusBoxPortrait(champIndex);
 -				setFlag(championAttributes, k0x0100_ChampionAttributeStatistics);
 -			} else
 -				setFlag(championAttributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x2000_ChampionAttributeWounds | k0x8000_ChampionAttributeActionHand);
 -		} else {
 -			_vm->_displayMan->f21_blitToScreen(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k8_StatusBoxDeadChampion), &box, k40_byteWidth, kM1_ColorNoTransparency, 29);
 -			_vm->_textMan->f53_printToLogicalScreen(championStatusBoxX + 1, 5, k13_ColorLightestGray, k1_ColorDarkGary, curChampion->_name);
 -			_vm->_menuMan->f386_drawActionIcon(champIndex);
 -
 -			clearFlag(curChampion->_attributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand);
 -			_vm->_eventMan->f77_hideMouse();
 -			return;
 -		}
 -	}
 -	if (!(curChampion->_currHealth)) {
 -		clearFlag(curChampion->_attributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand);
 -		_vm->_eventMan->f77_hideMouse();
 -		return;
 -	}
 -
 -	if (getFlag(championAttributes, k0x0080_ChampionAttributeNameTitle)) {
 -		Color nameColor = (champIndex == _g411_leaderIndex) ? k9_ColorGold : k13_ColorLightestGray;
 -		if (isInventoryChampion) {
 -			char *championName = curChampion->_name;
 -			_vm->_textMan->f52_printToViewport(3, 7, nameColor, championName);
 -			int16 championTitleX = 6 * strlen(championName) + 3;
 -			char titleFirstCharacter = curChampion->_title[0];
 -			if ((titleFirstCharacter != ',') && (titleFirstCharacter != ';') && (titleFirstCharacter != '-'))
 -				championTitleX += 6;
 -
 -			_vm->_textMan->f52_printToViewport(championTitleX, 7, nameColor, curChampion->_title);
 -			setFlag(championAttributes, k0x4000_ChampionAttributeViewport);
 -		} else {
 -			Box box;
 -			box._y1 = 0;
 -			box._y2 = 6;
 -			box._x1 = championStatusBoxX;
 -			box._x2 = box._x1 + 42;
 -			_vm->_displayMan->D24_fillScreenBox(box, k1_ColorDarkGary);
 -			_vm->_textMan->f53_printToLogicalScreen(championStatusBoxX + 1, 5, nameColor, k1_ColorDarkGary, curChampion->_name);
 -		}
 -	}
 -	if (getFlag(championAttributes, k0x0100_ChampionAttributeStatistics)) {
 -		f287_drawChampionBarGraphs(champIndex);
 -		if (isInventoryChampion) {
 -			f290_drawHealthStaminaManaValues(curChampion);
 -			int16 nativeBitmapIndex;
 -			if ((curChampion->_food < 0) || (curChampion->_water < 0) || (curChampion->_poisonEventCount))
 -				nativeBitmapIndex = k34_SlotBoxWoundedIndice;
 -			else
 -				nativeBitmapIndex = k33_SlotBoxNormalIndice;
 -
 -			_vm->_displayMan->f20_blitToViewport(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndex), gBoxMouth, k16_byteWidth, k12_ColorDarkestGray, 18);
 -			nativeBitmapIndex = k33_SlotBoxNormalIndice;
 -			for (int i = k1_ChampionStatStrength; i <= k6_ChampionStatAntifire; i++) {
 -				if ((curChampion->_statistics[i][k1_ChampionStatCurrent] < curChampion->_statistics[i][k0_ChampionStatMaximum])) {
 -					nativeBitmapIndex = k34_SlotBoxWoundedIndice;
 -					break;
 -				}
 -			}
 -			_vm->_displayMan->f20_blitToViewport(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndex), gBoxEye, k16_byteWidth, k12_ColorDarkestGray, 18);
 -			setFlag(championAttributes, k0x4000_ChampionAttributeViewport);
 -		}
 -	}
 -	if (getFlag(championAttributes, k0x2000_ChampionAttributeWounds)) {
 -		for (int i = isInventoryChampion ? k5_ChampionSlotFeet : k1_ChampionSlotActionHand; i >= k0_ChampionSlotReadyHand; i--)
 -			f291_drawSlot(champIndex, i);
 -
 -		if (isInventoryChampion)
 -			setFlag(championAttributes, k0x4000_ChampionAttributeViewport);
 -	}
 -	if (getFlag(championAttributes, k0x0200_ChampionAttributeLoad) && isInventoryChampion) {
 -		uint16 maxLoad = f309_getMaximumLoad(curChampion);
 -		Color loadColor;
 -		if (curChampion->_load > maxLoad)
 -			loadColor = k8_ColorRed;
 -		else if (((long)curChampion->_load << 3) > ((long)maxLoad * 5))
 -			loadColor = k11_ColorYellow;
 -		else
 -			loadColor = k13_ColorLightestGray;
 -
 -		_vm->_textMan->f52_printToViewport(104, 132, loadColor, "LOAD ");
 -		maxLoad = curChampion->_load / 10;
 -		strcpy(_vm->_g353_stringBuildBuffer, f288_getStringFromInteger(maxLoad, true, 3).c_str());
 -		strcat(_vm->_g353_stringBuildBuffer, ".");
 -		maxLoad = curChampion->_load - (maxLoad * 10);
 -		strcat(_vm->_g353_stringBuildBuffer, f288_getStringFromInteger(maxLoad, false, 1).c_str());
 -		strcat(_vm->_g353_stringBuildBuffer, "/");
 -		maxLoad = (f309_getMaximumLoad(curChampion) + 5) / 10;
 -		strcat(_vm->_g353_stringBuildBuffer, f288_getStringFromInteger(maxLoad, true, 3).c_str());
 -		strcat(_vm->_g353_stringBuildBuffer, " KG");
 -		_vm->_textMan->f52_printToViewport(148, 132, loadColor, _vm->_g353_stringBuildBuffer);
 -		setFlag(championAttributes, k0x4000_ChampionAttributeViewport);
 -	}
 -	uint16 championIconIndex = M26_championIconIndex(curChampion->_cell, _vm->_dungeonMan->_g308_partyDir);
 -	if (getFlag(championAttributes, k0x0400_ChampionAttributeIcon) && (_vm->_eventMan->_g599_useChampionIconOrdinalAsMousePointerBitmap != _vm->M0_indexToOrdinal(championIconIndex))) {
 -		_vm->_displayMan->D24_fillScreenBox(g54_BoxChampionIcons[championIconIndex], g46_ChampionColor[champIndex]);
 -		_vm->_displayMan->f132_blitToBitmap(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k28_ChampionIcons), _vm->_displayMan->_g348_bitmapScreen, g54_BoxChampionIcons[championIconIndex], M26_championIconIndex(curChampion->_dir, _vm->_dungeonMan->_g308_partyDir) * 19, 0, k40_byteWidth, k160_byteWidthScreen, k12_ColorDarkestGray, 14, k200_heightScreen);
 -	}
 -	if (getFlag(championAttributes, k0x0800_ChampionAttributePanel) && isInventoryChampion) {
 -		if (_vm->_g333_pressingMouth)
 -			_vm->_inventoryMan->f345_drawPanelFoodWaterPoisoned();
 -		else if (_vm->_g331_pressingEye) {
 -			if (_g415_leaderEmptyHanded)
 -				_vm->_inventoryMan->f351_drawChampionSkillsAndStatistics();
 -		} else
 -			_vm->_inventoryMan->f347_drawPanel();
 -
 -		setFlag(championAttributes, k0x4000_ChampionAttributeViewport);
 -	}
 -	if (getFlag(championAttributes, k0x8000_ChampionAttributeActionHand)) {
 -		f291_drawSlot(champIndex, k1_ChampionSlotActionHand);
 -		_vm->_menuMan->f386_drawActionIcon(champIndex);
 -		if (isInventoryChampion)
 -			setFlag(championAttributes, k0x4000_ChampionAttributeViewport);
 -	}
 -	if (getFlag(championAttributes, k0x4000_ChampionAttributeViewport))
 -		_vm->_displayMan->f97_drawViewport(k0_viewportNotDungeonView);
 -
 -	clearFlag(curChampion->_attributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand);
 -	_vm->_eventMan->f77_hideMouse();
 -}
 -
 -uint16 ChampionMan::M26_championIconIndex(int16 val, Direction dir) {
 -	return ((val + 4 - dir) & 0x3);
 -}
 -
 -void ChampionMan::f290_drawHealthStaminaManaValues(Champion* champ) {
 -	f289_drawHealthOrStaminaOrManaValue(116, champ->_currHealth, champ->_maxHealth);
 -	f289_drawHealthOrStaminaOrManaValue(124, champ->_currStamina, champ->_maxStamina);
 -	f289_drawHealthOrStaminaOrManaValue(132, champ->_currMana, champ->_maxMana);
 -}
 -
 -void ChampionMan::f291_drawSlot(uint16 champIndex, int16 slotIndex) {
 -	int16 nativeBitmapIndex = -1;
 -	Champion *champ = &_gK71_champions[champIndex];
 -	bool isInventoryChamp = (_vm->_inventoryMan->_g432_inventoryChampionOrdinal == _vm->M0_indexToOrdinal(champIndex));
 -
 -	uint16 slotBoxIndex;
 -	if (!isInventoryChamp) {
 -		// If drawing a slot for a champion other than the champion whose inventory is open
 -		if ((slotIndex > k1_ChampionSlotActionHand) || (_g299_candidateChampionOrdinal == _vm->M0_indexToOrdinal(champIndex)))
 -			return;
 -		slotBoxIndex = (champIndex << 1) + slotIndex;
 -	} else
 -		slotBoxIndex = k8_SlotBoxInventoryFirstSlot + slotIndex;
 -
 -	Thing thing;
 -	if (slotIndex >= k30_ChampionSlotChest_1)
 -		thing = _vm->_inventoryMan->_g425_chestSlots[slotIndex - k30_ChampionSlotChest_1];
 -	else
 -		thing = champ->getSlot((ChampionSlot)slotIndex);
 -
 -	SlotBox *slotBox = &_vm->_objectMan->_g30_slotBoxes[slotBoxIndex];
 -	Box box;
 -	box._x1 = slotBox->_x - 1;
 -	box._y1 = slotBox->_y - 1;
 -	box._x2 = box._x1 + 17;
 -	box._y2 = box._y1 + 17;
 -
 -	if (!isInventoryChamp)
 -		_vm->_eventMan->f77_hideMouse();
 -
 -	int16 iconIndex;
 -	if (thing == Thing::_none) {
 -		if (slotIndex <= k5_ChampionSlotFeet) {
 -			iconIndex = k212_IconIndiceReadyHand + (slotIndex << 1);
 -			if (champ->getWoundsFlag((ChampionWound)(1 << slotIndex))) {
 -				iconIndex++;
 -				nativeBitmapIndex = k34_SlotBoxWoundedIndice;
 -			} else
 -				nativeBitmapIndex = k33_SlotBoxNormalIndice;
 -		} else {
 -			if ((slotIndex >= k10_ChampionSlotNeck) && (slotIndex <= k13_ChampionSlotBackpackLine_1_1))
 -				iconIndex = k208_IconIndiceNeck + (slotIndex - k10_ChampionSlotNeck);
 -			else
 -				iconIndex = k204_IconIndiceEmptyBox;
 -		}
 -	} else {
 -		iconIndex = _vm->_objectMan->f33_getIconIndex(thing); // BUG0_35
 -		if (isInventoryChamp && (slotIndex == k1_ChampionSlotActionHand) && ((iconIndex == k144_IconIndiceContainerChestClosed) || (iconIndex == k30_IconIndiceScrollOpen))) {
 -			iconIndex++;
 -		} // BUG2_00
 -		if (slotIndex <= k5_ChampionSlotFeet) {
 -			if (champ->getWoundsFlag((ChampionWound)(1 << slotIndex)))
 -				nativeBitmapIndex = k34_SlotBoxWoundedIndice;
 -			else
 -				nativeBitmapIndex = k33_SlotBoxNormalIndice;
 -		}
 -	}
 -
 -	if ((slotIndex == k1_ChampionSlotActionHand) && (_vm->M0_indexToOrdinal(champIndex) == _g506_actingChampionOrdinal))
 -		nativeBitmapIndex = k35_SlotBoxActingHandIndice;
 -
 -	if (nativeBitmapIndex != -1) {
 -		_vm->_displayMan->_g578_useByteBoxCoordinates = false;
 -		if (isInventoryChamp)
 -			_vm->_displayMan->f132_blitToBitmap(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndex),
 -												_vm->_displayMan->_g296_bitmapViewport, box, 0, 0, 16, k112_byteWidthViewport, k12_ColorDarkestGray);
 -		else
 -			_vm->_displayMan->f132_blitToBitmap(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndex),
 -												_vm->_displayMan->_g348_bitmapScreen, box, 0, 0, 16, k160_byteWidthScreen, k12_ColorDarkestGray);
 -	}
 -
 -	_vm->_objectMan->f38_drawIconInSlotBox(slotBoxIndex, iconIndex);
 -
 -	if (!isInventoryChamp)
 -		_vm->_eventMan->f78_showMouse();
 -}
 -
 -void ChampionMan::f281_renameChampion(Champion* champ) {
 -#define k1_RENAME_CHAMPION_NAME 1
 -#define k2_RENAME_CHAMPION_TITLE 2
 -	static const char underscoreCharacterString[2] = "_";
 -	static char renameChampionInputCharacterString[2] = " ";
 -	static const char reincarnateSpecialCharacters[6] = {',', '.', ';', ':', ' '};
 -
 -	Box displayBox;
 -	displayBox._y1 = 3;
 -	displayBox._y2 = 8;
 -	displayBox._x1 = 3;
 -	displayBox._x2 = displayBox._x1 + 167;
 -
 -	_vm->_displayMan->f135_fillBoxBitmap(_vm->_displayMan->_g296_bitmapViewport, displayBox, k12_ColorDarkestGray, k112_byteWidthViewport, k136_heightViewport);
 -	_vm->_displayMan->f20_blitToViewport(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k27_PanelRenameChampionIndice), g32_BoxPanel, k72_byteWidth, k4_ColorCyan, 73);
 -	_vm->_textMan->f52_printToViewport(177, 58, k13_ColorLightestGray, "_______");
 -	_vm->_textMan->f52_printToViewport(105, 76, k13_ColorLightestGray, "___________________");
 -	_vm->_eventMan->f78_showMouse();
 -	_vm->_displayMan->f97_drawViewport(k0_viewportNotDungeonView);
 -	_vm->_eventMan->f67_setMousePointerToNormal(k0_pointerArrow);
 -	_vm->_eventMan->f77_hideMouse();
 -	uint16 curCharacterIndex = 0;
 -	champ->_name[curCharacterIndex] = '\0';
 -	champ->_title[0] = '\0';
 -	int16 renamedChampionStringMode = k1_RENAME_CHAMPION_NAME;
 -	char *renamedChampionString = champ->_name;
 -	int16 textPosX = 177;
 -	int16 textPosY = 91;
 -
 -	for (;;) { /*_Infinite loop_*/
 -		bool championTitleIsFull = ((renamedChampionStringMode == k2_RENAME_CHAMPION_TITLE) && (curCharacterIndex == 19));
 -		if (!championTitleIsFull) {
 -			_vm->_eventMan->f78_showMouse();
 -			_vm->_textMan->f40_printTextToBitmap(_vm->_displayMan->_g348_bitmapScreen, k160_byteWidthScreen, textPosX, textPosY, k9_ColorGold, k12_ColorDarkestGray, underscoreCharacterString, k200_heightScreen);
 -			_vm->_eventMan->f77_hideMouse();
 -		}
 -
 -		int16 curCharacter = 256;
 -		while (curCharacter == 256) {
 -			Common::Event event;
 -			Common::EventType eventType = _vm->_eventMan->processInput(&event, &event);
 -			_vm->_displayMan->updateScreen();
 -			_vm->f22_delay(1);
 -
 -			if (eventType == Common::EVENT_LBUTTONDOWN) {
 -				// If left mouse button status has changed
 -				Common::Point mousePos = _vm->_eventMan->getMousePos();
 -				if ((renamedChampionStringMode == k2_RENAME_CHAMPION_TITLE || (curCharacterIndex > 0)) && (mousePos.x >= 197) && (mousePos.x <= 215) && (mousePos.y >= 147) && (mousePos.y <= 155)) { /* Coordinates of 'OK' button */
 -					int16 characterIndexBackup = curCharacterIndex;
 -					char L0821_ac_ChampionNameBackupString[8];
 -					renamedChampionString = champ->_name;
 -					strcpy(L0821_ac_ChampionNameBackupString, renamedChampionString);
 -					curCharacterIndex = strlen(renamedChampionString);
 -					// Replace space characters on the right of the champion name by '\0' characters
 -					while (renamedChampionString[--curCharacterIndex] == ' ')
 -						renamedChampionString[curCharacterIndex] = '\0';
 -
 -					bool found = false;
 -					for (uint16 idx = k0_ChampionFirst; idx < _g305_partyChampionCount - 1; idx++) {
 -						if (!strcmp(_gK71_champions[idx]._name, renamedChampionString)) {
 -							// If an existing champion already has the specified name for the new champion
 -							found = true;
 -							break;
 -						}
 -					}
 -					if (!found)
 -						return;
 -
 -					if (renamedChampionStringMode == k2_RENAME_CHAMPION_TITLE)
 -						renamedChampionString = champ->_title;
 -
 -					strcpy(renamedChampionString = champ->_name, L0821_ac_ChampionNameBackupString);
 -					curCharacterIndex = characterIndexBackup;
 -				} else {
 -					if ((mousePos.x >= 107) && (mousePos.x <= 175) && (mousePos.y >= 147) && (mousePos.y <= 155)) { /* Coordinates of 'BACKSPACE' button */
 -						curCharacter = '\b';
 -						break;
 -					}
 -#if 0
 -					if ((mousePos.x < 107) || (mousePos.x > 215) || (mousePos.y < 116) || (mousePos.y > 144)) {/* Coordinates of table of all other characters */
 -						//goto T0281023;
 -					}
 -					if (!((mousePos.x + 4) % 10) || (!((mousePos.y + 5) % 10) && ((mousePos.x < 207) || (mousePos.y != 135)))) {
 -						//goto T0281023;
 -					}
 -#endif
 -					curCharacter = 'A' + (11 * ((mousePos.y - 116) / 10)) + ((mousePos.x - 107) / 10);
 -					if ((curCharacter == 86) || (curCharacter == 97)) {
 -						// The 'Return' button occupies two cells in the table
 -						curCharacter = '\r'; /* Carriage return */
 -						break;
 -					}
 -
 -					if (curCharacter >= 87)
 -						// Compensate for the first cell occupied by 'Return' button
 -						curCharacter--;
 -
 -					if (curCharacter > 'Z')
 -						curCharacter = reincarnateSpecialCharacters[(curCharacter - 'Z') - 1];
 -
 -					break;
 -				}
 -			} else if (eventType == Common::EVENT_KEYDOWN)
 -				curCharacter = event.kbd.ascii;
 -		}
 -
 -		if ((curCharacter >= 'a') && (curCharacter <= 'z'))
 -			curCharacter -= 32; // Convert to uppercase
 -
 -		if (((curCharacter >= 'A') && (curCharacter <= 'Z')) || (curCharacter == '.') || (curCharacter == ',') || (curCharacter == ';') || (curCharacter == ':') || (curCharacter == ' ')) {
 -			if ((curCharacter != ' ') || curCharacterIndex != 0) {
 -				if (!championTitleIsFull) {
 -					renameChampionInputCharacterString[0] = curCharacter;
 -					_vm->_eventMan->f78_showMouse();
 -					_vm->_textMan->f40_printTextToBitmap(_vm->_displayMan->_g348_bitmapScreen, k160_byteWidthScreen, textPosX, textPosY, k13_ColorLightestGray, k12_ColorDarkestGray, renameChampionInputCharacterString, k200_heightScreen);
 -					_vm->_eventMan->f77_hideMouse();
 -					renamedChampionString[curCharacterIndex++] = curCharacter;
 -					renamedChampionString[curCharacterIndex] = '\0';
 -					textPosX += 6;
 -					if ((renamedChampionStringMode == k1_RENAME_CHAMPION_NAME) && (curCharacterIndex == 7)) {
 -						renamedChampionStringMode = k2_RENAME_CHAMPION_TITLE;
 -						renamedChampionString = champ->_title;
 -						textPosX = 105;
 -						textPosY = 109;
 -						curCharacterIndex = 0;
 -					}
 -				}
 -			}
 -		} else if (curCharacter == '\r') { // Carriage return
 -			if ((renamedChampionStringMode == k1_RENAME_CHAMPION_NAME) && (curCharacterIndex > 0)) {
 -				_vm->_eventMan->f78_showMouse();
 -				_vm->_textMan->f40_printTextToBitmap(_vm->_displayMan->_g348_bitmapScreen, k160_byteWidthScreen, textPosX, textPosY, k13_ColorLightestGray, k12_ColorDarkestGray, underscoreCharacterString, k200_heightScreen);
 -				_vm->_eventMan->f77_hideMouse();
 -				renamedChampionStringMode = k2_RENAME_CHAMPION_TITLE;
 -				renamedChampionString = champ->_title;
 -				textPosX = 105;
 -				textPosY = 109;
 -				curCharacterIndex = 0;
 -			}
 -		} else if (curCharacter == '\b') { // Backspace
 -			if ((renamedChampionStringMode == k1_RENAME_CHAMPION_NAME) && (curCharacterIndex == 0))
 -				continue;
 -
 -			if (!championTitleIsFull) {
 -				_vm->_eventMan->f78_showMouse();
 -				_vm->_textMan->f40_printTextToBitmap(_vm->_displayMan->_g348_bitmapScreen, k160_byteWidthScreen, textPosX, textPosY, k13_ColorLightestGray, k12_ColorDarkestGray, underscoreCharacterString, k200_heightScreen);
 -				_vm->_eventMan->f77_hideMouse();
 -			}
 -			if (curCharacterIndex == 0) {
 -				renamedChampionString = champ->_name;
 -				curCharacterIndex = strlen(renamedChampionString) - 1;
 -				renamedChampionStringMode = k1_RENAME_CHAMPION_NAME;
 -				textPosX = 177 + (curCharacterIndex * 6);
 -				textPosY = 91;
 -			} else {
 -				curCharacterIndex--;
 -				textPosX -= 6;
 -			}
 -			renamedChampionString[curCharacterIndex] = '\0';
 -		}
 -	}
 -}
 -
 -uint16 ChampionMan::f303_getSkillLevel(int16 champIndex, uint16 skillIndex) {
 -	if (_g300_partyIsSleeping)
 -		return 1;
 -
 -	bool ignoreTmpExp = getFlag(skillIndex, k0x8000_IgnoreTemporaryExperience);
 -	bool ignoreObjModifiers = getFlag(skillIndex, k0x4000_IgnoreObjectModifiers);
 -	clearFlag(skillIndex, k0x8000_IgnoreTemporaryExperience | k0x4000_IgnoreObjectModifiers);
 -	Champion *champ = &_gK71_champions[champIndex];
 -	Skill *skill = &champ->_skills[skillIndex];
 -	int32 exp = skill->_experience;
 -	if (!ignoreTmpExp)
 -		exp += skill->_temporaryExperience;
 -
 -	if (skillIndex > k3_ChampionSkillWizard) {
 -		// Hidden skill
 -		skill = &champ->_skills[(skillIndex - k4_ChampionSkillSwing) >> 2];
 -		exp += skill->_experience; // Add experience in the base skill
 -		if (!ignoreTmpExp)
 -			exp += skill->_temporaryExperience;
 -
 -		exp >>= 1; // Halve experience to get average of base skill + hidden skill experience
 -	}
 -	int16 skillLevel = 1;
 -	while (exp >= 500) {
 -		exp >>= 1;
 -		skillLevel++;
 -	}
 -	if (!ignoreObjModifiers) {
 -		int16 actionHandIconIndex = _vm->_objectMan->f33_getIconIndex(champ->_slots[k1_ChampionSlotActionHand]);
 -		if (actionHandIconIndex == k27_IconIndiceWeaponTheFirestaff)
 -			skillLevel++;
 -		else if (actionHandIconIndex == k28_IconIndiceWeaponTheFirestaffComplete)
 -			skillLevel += 2;
 -
 -		int16 neckIconIndex = _vm->_objectMan->f33_getIconIndex(champ->_slots[k10_ChampionSlotNeck]);
 -		switch (skillIndex) {
 -		case k3_ChampionSkillWizard:
 -			if (neckIconIndex == k124_IconIndiceJunkPendantFeral)
 -				skillLevel += 1;
 -			break;
 -		case k13_ChampionSkillHeal:
 -			// The skill modifiers of these two objects are not cumulative
 -			if ((neckIconIndex == k120_IconIndiceJunkGemOfAges) || (actionHandIconIndex == k66_IconIndiceWeaponSceptreOfLyf)) 
 -				skillLevel += 1;
 -			break;
 -		case k14_ChampionSkillInfluence:
 -			if (neckIconIndex == k122_IconIndiceJunkMoonstone)
 -				skillLevel += 1;
 -			break;
 -		case k15_ChampionSkillDefend:
 -			if (neckIconIndex == k121_IconIndiceJunkEkkhardCross)
 -				skillLevel += 1;
 -			break;
 -		default:
 -			break;
 -		}
 -	}
 -	return skillLevel;
 -}
 -
 -}
 +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +*/ + +/* +* Based on the Reverse Engineering work of Christophe Fontanel, +* maintainer of the Dungeon Master Encyclopaedia (http://dmweb.free.fr/) +*/ + +#include "champion.h" +#include "dungeonman.h" +#include "eventman.h" +#include "menus.h" +#include "inventory.h" +#include "objectman.h" +#include "text.h" +#include "timeline.h" +#include "projexpl.h" +#include "group.h" +#include "movesens.h" + + +namespace DM { + +const char *g417_baseSkillName[4] = {"FIGHTER", "NINJA", "PRIEST", "WIZARD"}; + +Box gBoxMouth = Box(55, 72, 12, 29); // @ G0048_s_Graphic562_Box_Mouth  +Box gBoxEye = Box(11, 28, 12, 29); // @ G0049_s_Graphic562_Box_Eye  +Box g54_BoxChampionIcons[4] = { +	Box(281, 299,  0, 13), +	Box(301, 319,  0, 13), +	Box(301, 319, 15, 28), +	Box(281, 299, 15, 28)}; +Color g46_ChampionColor[4] = {(Color)7, (Color)11, (Color)8, (Color)14}; + +int16 g39_LightPowerToLightAmount[16] = {0, 5, 12, 24, 33, 40, 46, 51, 59, 68, 76, 82, 89, 94, 97, 100}; + +uint16 gSlotMasks[38] = {  // @ G0038_ai_Graphic562_SlotMasks +						   /* 30 for champion inventory, 8 for chest */ +	0xFFFF,   /* Ready Hand       Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Action Hand      Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0x0002,   /* Head             Head */ +	0x0008,   /* Torso            Torso */ +	0x0010,   /* Legs             Legs */ +	0x0020,   /* Feet             Feet */ +	0x0100,   /* Pouch 2          Pouch */ +	0x0080,   /* Quiver Line2 1   Quiver 2 */ +	0x0080,   /* Quiver Line1 2   Quiver 2 */ +	0x0080,   /* Quiver Line2 2   Quiver 2 */ +	0x0004,   /* Neck             Neck */ +	0x0100,   /* Pouch 1          Pouch */ +	0x0040,   /* Quiver Line1 1   Quiver 1 */ +	0xFFFF,   /* Backpack Line1 1 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line2 2 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line2 3 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line2 4 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line2 5 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line2 6 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line2 7 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line2 8 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line2 9 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line1 2 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line1 3 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line1 4 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line1 5 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line1 6 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line1 7 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line1 8 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0xFFFF,   /* Backpack Line1 9 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ +	0x0400,   /* Chest 1          Chest */ +	0x0400,   /* Chest 2          Chest */ +	0x0400,   /* Chest 3          Chest */ +	0x0400,   /* Chest 4          Chest */ +	0x0400,   /* Chest 5          Chest */ +	0x0400,   /* Chest 6          Chest */ +	0x0400,   /* Chest 7          Chest */ +	0x0400}; /* Chest 8          Chest */ + +Box gBoxChampionPortrait = Box(0, 31, 0, 28); // @ G0047_s_Graphic562_Box_ChampionPortrait  + +ChampionMan::ChampionMan(DMEngine *vm) : _vm(vm) { +	for (uint16 i = 0; i < 4; ++i) { +		_g409_championPendingDamage[i] = 0; +		_g410_championPendingWounds[i] = 0; +		_gK71_champions[i].resetToZero(); +	} +	_g305_partyChampionCount = 0; +	_g303_partyDead = false; +	_g414_leaderHandObject = Thing(0); +	_g411_leaderIndex = kM1_ChampionNone; +	_g299_candidateChampionOrdinal = 0; +	_g300_partyIsSleeping = false; +	_g506_actingChampionOrdinal = 0; +	_g413_leaderHandObjectIconIndex = (IconIndice)0; +	_g415_leaderEmptyHanded = false; +	_g407_party.resetToZero(); +	_g514_magicCasterChampionIndex = kM1_ChampionNone; +	_g420_mousePointerHiddenToDrawChangedObjIconOnScreen = false; +} + +bool ChampionMan::f329_isLeaderHandObjectThrown(int16 side) { +	if (_g411_leaderIndex == kM1_ChampionNone) { +		return false; +	} +	return f328_isObjectThrown(_g411_leaderIndex, kM1_ChampionSlotLeaderHand, side); +} + +bool ChampionMan::f328_isObjectThrown(uint16 champIndex, int16 slotIndex, int16 side) { +	bool throwingLeaderHandObjectFl = false; +	Thing curThing; +	Champion *curChampion = nullptr; +	Thing actionHandThing; + +	if (slotIndex < 0) { /* Throw object in leader hand, which is temporarily placed in action hand */ +		if (_g415_leaderEmptyHanded) +			return false; + +		curThing = f298_getObjectRemovedFromLeaderHand(); +		curChampion = &_gK71_champions[champIndex]; +		actionHandThing = curChampion->getSlot(k1_ChampionSlotActionHand); +		curChampion->setSlot(k1_ChampionSlotActionHand, curThing); +		slotIndex = k1_ChampionSlotActionHand; +		throwingLeaderHandObjectFl = true; +	} + +	int16 kineticEnergy = f312_getStrength(champIndex, slotIndex); +	if (throwingLeaderHandObjectFl) { +		// In this case, curChampion and actionHandThing are set. +		curChampion->setSlot((ChampionSlot)slotIndex, actionHandThing); +	} else { +		curThing = f300_getObjectRemovedFromSlot(champIndex, slotIndex); +		if (curThing == Thing::_none) +			return false; +	} + +	_vm->f064_SOUND_RequestPlay_CPSD(k16_soundCOMBAT_ATTACK_SKELETON_ANIMATED_ARMOUR_DETH_KNIGHT, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY, k1_soundModePlayIfPrioritized); +	f325_decrementStamina(champIndex, f305_getThrowingStaminaCost(curThing)); +	f330_disableAction(champIndex, 4); +	int16 experience = 8; +	int16 weaponKineticEnergy = 1; +	if (curThing.getType() == k5_WeaponThingType) { +		experience += 4; +		WeaponInfo *curWeapon = _vm->_dungeonMan->f158_getWeaponInfo(curThing); +		if (curWeapon->_class <= k12_WeaponClassPoisinDart) { +			weaponKineticEnergy = curWeapon->_kineticEnergy; +			experience += weaponKineticEnergy >> 2; +		} +	} +	f304_addSkillExperience(champIndex, k10_ChampionSkillThrow, experience); +	kineticEnergy += weaponKineticEnergy; +	int16 skillLevel = f303_getSkillLevel((ChampionIndex)champIndex, k10_ChampionSkillThrow); +	kineticEnergy += _vm->getRandomNumber(16) + (kineticEnergy >> 1) + skillLevel; +	int16 attack = f26_getBoundedValue((uint16)40, (uint16)((skillLevel << 3) + _vm->getRandomNumber(32)), (uint16)200); +	int16 stepEnergy = MAX(5, 11 - skillLevel); +	_vm->_projexpl->f212_projectileCreate(curThing, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY, +										  M21_normalizeModulo4(_vm->_dungeonMan->_g308_partyDir + side), +										  _vm->_dungeonMan->_g308_partyDir, kineticEnergy, attack, stepEnergy); +	_vm->_g311_projectileDisableMovementTicks = 4; +	_vm->_g312_lastProjectileDisabledMovementDirection = _vm->_dungeonMan->_g308_partyDir; +	f292_drawChampionState((ChampionIndex)champIndex); +	return true; +} + +uint16 ChampionMan::M27_getChampionPortraitX(uint16 index) { +	return ((index) & 0x7) << 5; +} + +uint16 ChampionMan::M28_getChampionPortraitY(uint16 index) { +	return ((index) >> 3) * 29; +} + +int16 ChampionMan::f279_getDecodedValue(char *string, uint16 characterCount) { +	int val = 0; +	for (uint16 i = 0; i < characterCount; ++i) { +		val = (val << 4) + (string[i] - 'A'); +	} +	return val; +} + +void ChampionMan::f289_drawHealthOrStaminaOrManaValue(int16 posY, int16 currVal, int16 maxVal) { +	Common::String tmp = f288_getStringFromInteger(currVal, true, 3); +	_vm->_textMan->f52_printToViewport(55, posY, k13_ColorLightestGray, tmp.c_str()); +	_vm->_textMan->f52_printToViewport(73, posY, k13_ColorLightestGray, "/"); +	tmp = f288_getStringFromInteger(maxVal, true, 3); +	_vm->_textMan->f52_printToViewport(79, posY, k13_ColorLightestGray, tmp.c_str()); +} + +uint16 ChampionMan::M70_handSlotIndex(uint16 slotBoxIndex) { +	return slotBoxIndex & 0x1; +} + +Common::String ChampionMan::f288_getStringFromInteger(uint16 val, bool padding, uint16 paddingCharCount) { +	Common::String valToStr = Common::String::format("%d", val); +	Common::String result; + +	if (padding) { +		for (int16 i = 0, end = paddingCharCount - valToStr.size(); i < end; ++i) +			result += ' '; +	} + +	return result += valToStr; +} + +void ChampionMan::f299_applyModifiersToStatistics(Champion *champ, int16 slotIndex, int16 iconIndex, int16 modifierFactor, Thing thing) { +	int16 statIndex = k0_ChampionStatLuck; +	int16 modifier = 0; +	ThingType thingType = thing.getType(); + +	bool cursed = false; +	if (((thingType == k5_WeaponThingType) || (thingType == k6_ArmourThingType)) +		&& (slotIndex >= k0_ChampionSlotReadyHand) && (slotIndex <= k12_ChampionSlotQuiverLine_1_1)) { +		if (thingType == k5_WeaponThingType) { +			Weapon *weapon = (Weapon *)_vm->_dungeonMan->f156_getThingData(thing); +			cursed = weapon->getCursed(); +		} else { +			// k6_ArmourThingType +			Armour *armour = (Armour *)_vm->_dungeonMan->f156_getThingData(thing); +			cursed = armour->getCursed(); +		} + +		if (cursed) { +			statIndex = k0_ChampionStatLuck; +			modifier = -3; +		} +	} + +	if (!cursed) { +		statIndex = (ChampionStatisticType)thingType; // variable sharing + +		if ((iconIndex == k137_IconIndiceJunkRabbitsFoot) && (slotIndex < k30_ChampionSlotChest_1)) { +			statIndex = k0_ChampionStatLuck; +			modifier = 10; +		} else if (slotIndex == k1_ChampionSlotActionHand) { +			if (iconIndex == k45_IconIndiceWeaponMaceOfOrder) { +				statIndex = k1_ChampionStatStrength; +				modifier = 5; +			} else { +				statIndex = k8_ChampionStatMana; +				if ((iconIndex >= k20_IconIndiceWeaponStaffOfClawsEmpty) && (iconIndex <= k22_IconIndiceWeaponStaffOfClawsFull)) { +					modifier = 4; +				} else { +					switch (iconIndex) { +					case k38_IconIndiceWeaponDeltaSideSplitter: +						modifier = 1; +						break; +					case k41_IconIndiceWeaponTheInquisitorDragonFang: +						modifier = 2; +						break; +					case k40_IconIndiceWeaponVorpalBlade: +						modifier = 4; +						break; +					case k58_IconIndiceWeaponStaff: +						modifier = 2; +						break; +					case k59_IconIndiceWeaponWand: +						modifier = 1; +						break; +					case k60_IconIndiceWeaponTeowand: +						modifier = 6; +						break; +					case k61_IconIndiceWeaponYewStaff: +						modifier = 4; +						break; +					case k62_IconIndiceWeaponStaffOfManarStaffOfIrra: +						modifier = 10; +						break; +					case k63_IconIndiceWeaponSnakeStaffCrossOfNeta: +						modifier = 8; +						break; +					case k64_IconIndiceWeaponTheConduitSerpentStaff: +						modifier = 16; +						break; +					case k65_IconIndiceWeaponDragonSpit: +						modifier = 7; +						break; +					case k66_IconIndiceWeaponSceptreOfLyf: +						modifier = 5; +						break; +					default: +						break; +					} +				} +			} +		} else if (slotIndex == k4_ChampionSlotLegs) { +			if (iconIndex == k142_IconIndiceArmourPowertowers) { +				statIndex = k1_ChampionStatStrength; +				modifier = 10; +			} +		} else if (slotIndex == k2_ChampionSlotHead) { +			switch (iconIndex) { +			case k104_IconIndiceArmourCrownOfNerra: +				statIndex = k3_ChampionStatWisdom; +				modifier = 10; +				break; +			case k140_IconIndiceArmourDexhelm: +				statIndex = k2_ChampionStatDexterity; +				modifier = 10; +				break; +			default: +				break; +			} +		} else if (slotIndex == k3_ChampionSlotTorso) { +			switch (iconIndex) { +			case k141_IconIndiceArmourFlamebain: +				statIndex = k6_ChampionStatAntifire; +				modifier = 12; +				break; +			case k81_IconIndiceArmourCloakOfNight: +				statIndex = k2_ChampionStatDexterity; +				modifier = 8; +				break; +			default: +				break; +			} +		} else if (slotIndex == k10_ChampionSlotNeck) { +			switch (iconIndex) { +			case k10_IconIndiceJunkJewelSymalUnequipped: +			case k11_IconIndiceJunkJewelSymalEquipped: +				statIndex = k5_ChampionStatAntimagic; +				modifier = 15; +				break; +			case k81_IconIndiceArmourCloakOfNight: +				statIndex = k2_ChampionStatDexterity; +				modifier = 8; +				break; +			case k122_IconIndiceJunkMoonstone: +				statIndex = k8_ChampionStatMana; +				modifier = 3; +				break; +			default: +				break; +			} +		} +	} + +	if (modifier) { +		modifier *= modifierFactor; +		//statIndex is set when modifier is set +		if (statIndex == k8_ChampionStatMana) { +			champ->_maxMana += modifier; +		} else if (statIndex < k6_ChampionStatAntifire + 1) { +			for (uint16 statValIndex = k0_ChampionStatMaximum; statValIndex <= k2_ChampionStatMinimum; ++statValIndex) { +				champ->getStatistic((ChampionStatisticType)statIndex, (ChampionStatisticValue)statValIndex) += modifier; +			} +		} +	} +} + +bool ChampionMan::f295_hasObjectIconInSlotBoxChanged(int16 slotBoxIndex, Thing thing) { +	ObjectMan &objMan = *_vm->_objectMan; + +	IconIndice currIconIndex = objMan.f39_getIconIndexInSlotBox(slotBoxIndex); +	if (((currIconIndex < k32_IconIndiceWeaponDagger) && (currIconIndex >= k0_IconIndiceJunkCompassNorth)) +		|| ((currIconIndex >= k148_IconIndicePotionMaPotionMonPotion) && (currIconIndex <= k163_IconIndicePotionWaterFlask)) +		|| (currIconIndex == k195_IconIndicePotionEmptyFlask)) { +		IconIndice newIconIndex = objMan.f33_getIconIndex(thing); +		if (newIconIndex != currIconIndex) { +			if ((slotBoxIndex < k8_SlotBoxInventoryFirstSlot) && !_g420_mousePointerHiddenToDrawChangedObjIconOnScreen) { +				_g420_mousePointerHiddenToDrawChangedObjIconOnScreen = true; +				_vm->_eventMan->f77_hideMouse(); +			} +			objMan.f38_drawIconInSlotBox(slotBoxIndex, newIconIndex); +			return true; +		} +	} + +	return false; +} + +void ChampionMan::f296_drawChangedObjectIcons() { +	InventoryMan &invMan = *_vm->_inventoryMan; +	ObjectMan &objMan = *_vm->_objectMan; +	MenuMan &menuMan = *_vm->_menuMan; + +	uint16 invChampOrdinal = invMan._g432_inventoryChampionOrdinal; +	if (_g299_candidateChampionOrdinal && !invChampOrdinal) +		return; + +	_g420_mousePointerHiddenToDrawChangedObjIconOnScreen = false; +	IconIndice leaderHandObjIconIndex = _g413_leaderHandObjectIconIndex; + +	if (((leaderHandObjIconIndex < k32_IconIndiceWeaponDagger) && (leaderHandObjIconIndex >= k0_IconIndiceJunkCompassNorth))	// < instead of <= is correct +		|| ((leaderHandObjIconIndex >= k148_IconIndicePotionMaPotionMonPotion) && (leaderHandObjIconIndex <= k163_IconIndicePotionWaterFlask)) +		|| (leaderHandObjIconIndex == k195_IconIndicePotionEmptyFlask)) { +		IconIndice iconIndex = objMan.f33_getIconIndex(_g414_leaderHandObject); +		if (iconIndex != leaderHandObjIconIndex) { +			_g420_mousePointerHiddenToDrawChangedObjIconOnScreen = true; +			_vm->_eventMan->f77_hideMouse(); +			objMan.f36_extractIconFromBitmap(iconIndex, objMan._g412_objectIconForMousePointer); +			_vm->_eventMan->f68_setPointerToObject(_vm->_objectMan->_g412_objectIconForMousePointer); +			_g413_leaderHandObjectIconIndex = iconIndex; +			objMan.f34_drawLeaderObjectName(_g414_leaderHandObject); +		} +	} + +	for (uint16 slotBoxIndex = 0; slotBoxIndex < (_g305_partyChampionCount * 2); ++slotBoxIndex) { +		int16 champIndex = slotBoxIndex >> 1; +		if (invChampOrdinal == _vm->M0_indexToOrdinal(champIndex)) +			continue; + +		if (f295_hasObjectIconInSlotBoxChanged(slotBoxIndex, _gK71_champions[champIndex].getSlot((ChampionSlot)M70_handSlotIndex(slotBoxIndex))) +			&& (M70_handSlotIndex(slotBoxIndex) == k1_ChampionSlotActionHand)) { + +			menuMan.f386_drawActionIcon((ChampionIndex)champIndex); +		} +	} + +	if (invChampOrdinal) { +		Champion *champ = &_gK71_champions[_vm->M1_ordinalToIndex(invChampOrdinal)]; +		Thing *thing = &champ->getSlot(k0_ChampionSlotReadyHand); +		uint16 drawViewport = 0; + +		for (uint16 slotIndex = k0_ChampionSlotReadyHand; slotIndex < k30_ChampionSlotChest_1; slotIndex++, thing++) { +			uint16 objIconChanged = f295_hasObjectIconInSlotBoxChanged(slotIndex + k8_SlotBoxInventoryFirstSlot, *thing) ? 1 : 0; +			drawViewport |= objIconChanged; +			if (objIconChanged && (slotIndex == k1_ChampionSlotActionHand)) { +				menuMan.f386_drawActionIcon((ChampionIndex)_vm->M1_ordinalToIndex(invChampOrdinal)); +			} +		} + +		if (invMan._g424_panelContent = k4_PanelContentChest) { +			thing = invMan._g425_chestSlots; +			for (int16 slotIndex = 0; slotIndex < 8; ++slotIndex, thing++) { +				drawViewport |= (f295_hasObjectIconInSlotBoxChanged(slotIndex + k38_SlotBoxChestFirstSlot, *thing) ? 1 : 0); +			} +		} + +		if (drawViewport) { +			champ->setAttributeFlag(k0x4000_ChampionAttributeViewport, true); +			f292_drawChampionState((ChampionIndex)_vm->M1_ordinalToIndex(invChampOrdinal)); +		} +	} + +	if (_g420_mousePointerHiddenToDrawChangedObjIconOnScreen) +		_vm->_eventMan->f78_showMouse(); +} + +void ChampionMan::f301_addObjectInSlot(ChampionIndex champIndex, Thing thing, ChampionSlot slotIndex) { +	InventoryMan &invMan = *_vm->_inventoryMan; +	DungeonMan &dunMan = *_vm->_dungeonMan; +	ObjectMan &objMan = *_vm->_objectMan; +	MenuMan &menuMan = *_vm->_menuMan; + +	if (thing == Thing::_none) +		return; + +	Champion *champ = &_gK71_champions[champIndex]; + +	if (slotIndex >= k30_ChampionSlotChest_1) { +		invMan._g425_chestSlots[slotIndex - k30_ChampionSlotChest_1] = thing; +	} else { +		champ->setSlot(slotIndex, thing); +	} + +	champ->_load += dunMan.f140_getObjectWeight(thing); +	champ->setAttributeFlag(k0x0200_ChampionAttributeLoad, true); +	IconIndice iconIndex = objMan.f33_getIconIndex(thing); +	bool isInventoryChampion = (_vm->M0_indexToOrdinal(champIndex) == invMan._g432_inventoryChampionOrdinal); +	f299_applyModifiersToStatistics(champ, slotIndex, iconIndex, 1, thing); +	uint16 *rawObjPtr = dunMan.f156_getThingData(thing); + +	if (slotIndex < k2_ChampionSlotHead) { +		if (slotIndex == k1_ChampionSlotActionHand) { +			champ->setAttributeFlag(k0x8000_ChampionAttributeActionHand, true); +			if (_g506_actingChampionOrdinal == _vm->M0_indexToOrdinal(champIndex)) +				menuMan.f388_clearActingChampion(); + +			if ((iconIndex >= k30_IconIndiceScrollOpen) && (iconIndex <= k31_IconIndiceScrollClosed)) { +				((Scroll *)rawObjPtr)->setClosed(false); +				f296_drawChangedObjectIcons(); +			} +		} + +		if (iconIndex = k4_IconIndiceWeaponTorchUnlit) { +			((Weapon *)rawObjPtr)->setLit(true); +			_vm->_inventoryMan->f337_setDungeonViewPalette(); +			f296_drawChangedObjectIcons(); +		} else if (isInventoryChampion && (slotIndex == k1_ChampionSlotActionHand) && +			((iconIndex == k144_IconIndiceContainerChestClosed) || ((iconIndex >= k30_IconIndiceScrollOpen) && (iconIndex <= k31_IconIndiceScrollClosed)))) { +			champ->setAttributeFlag(k0x0800_ChampionAttributePanel, true); +		} +	} else if (slotIndex == k10_ChampionSlotNeck) { +		if ((iconIndex >= k12_IconIndiceJunkIllumuletUnequipped) && (iconIndex <= k13_IconIndiceJunkIllumuletEquipped)) { +			((Junk *)rawObjPtr)->setChargeCount(1); +			_g407_party._magicalLightAmount += g39_LightPowerToLightAmount[2]; +			_vm->_inventoryMan->f337_setDungeonViewPalette(); +			iconIndex = (IconIndice)(iconIndex + 1); +		} else if ((iconIndex >= k10_IconIndiceJunkJewelSymalUnequipped) && (iconIndex <= k11_IconIndiceJunkJewelSymalEquipped)) { +			((Junk *)rawObjPtr)->setChargeCount(1); +			iconIndex = (IconIndice)(iconIndex + 1); +		} +	} + +	f291_drawSlot(champIndex, slotIndex); +	if (isInventoryChampion) +		champ->setAttributeFlag(k0x4000_ChampionAttributeViewport, true); +} + +int16 ChampionMan::f315_getScentOrdinal(int16 mapX, int16 mapY) { +	int16 scentIndex = _g407_party._scentCount; + +	if (scentIndex) { +		Scent searchedScent; +		searchedScent.setMapX(mapX); +		searchedScent.setMapY(mapY); +		searchedScent.setMapIndex(_vm->_dungeonMan->_g272_currMapIndex); +		uint16 searchedScentRedEagle = searchedScent.toUint16(); +		Scent *scent = &_g407_party._scents[scentIndex--]; +		do { +			if ((*(--scent)).toUint16() == searchedScentRedEagle) { +				return _vm->M0_indexToOrdinal(scentIndex); +			} +		} while (scentIndex--); +	} +	return 0; +} + +Thing ChampionMan::f298_getObjectRemovedFromLeaderHand() { +	_g415_leaderEmptyHanded = true; +	Thing leaderHandObject = _g414_leaderHandObject; + +	if (leaderHandObject != Thing::_none) { +		_g414_leaderHandObject = Thing::_none; +		_g413_leaderHandObjectIconIndex = kM1_IconIndiceNone; +		_vm->_eventMan->f78_showMouse(); +		_vm->_objectMan->f35_clearLeaderObjectName(); +		_vm->_eventMan->f69_setMousePointer(); +		_vm->_eventMan->f77_hideMouse(); +		if (_g411_leaderIndex != kM1_ChampionNone) { +			_gK71_champions[_g411_leaderIndex]._load -= _vm->_dungeonMan->f140_getObjectWeight(leaderHandObject); +			setFlag(_gK71_champions[_g411_leaderIndex]._attributes, k0x0200_ChampionAttributeLoad); +			f292_drawChampionState(_g411_leaderIndex); +		} +	} +	return leaderHandObject; +} + +uint16 ChampionMan::f312_getStrength(int16 champIndex, int16 slotIndex) { +	Champion *curChampion = &_gK71_champions[champIndex]; +	int16 strength = _vm->getRandomNumber(16) + curChampion->_statistics[k1_ChampionStatStrength][k1_ChampionStatCurrent]; +	Thing curThing = curChampion->_slots[slotIndex]; +	uint16 objectWeight = _vm->_dungeonMan->f140_getObjectWeight(curThing); +	uint16 oneSixteenthMaximumLoad = f309_getMaximumLoad(curChampion) >> 4; + +	if (objectWeight <= oneSixteenthMaximumLoad) { +		strength += objectWeight - 12; +	} else { +		int16 loadThreshold = oneSixteenthMaximumLoad + ((oneSixteenthMaximumLoad - 12) >> 1); +		if (objectWeight <= loadThreshold) { +			strength += (objectWeight - oneSixteenthMaximumLoad) >> 1; +		} else { +			strength -= (objectWeight - loadThreshold) << 1; +		} +	} +	if (curThing.getType() == k5_WeaponThingType) { +		WeaponInfo *weaponInfo = _vm->_dungeonMan->f158_getWeaponInfo(curThing); +		strength += weaponInfo->_strength; +		uint16 skillLevel = 0; +		uint16 weaponClass = weaponInfo->_class; +		if ((weaponClass == k0_WeaponClassSwingWeapon) || (weaponClass == k2_WeaponClassDaggerAndAxes)) { +			skillLevel = f303_getSkillLevel(champIndex, k4_ChampionSkillSwing); +		} +		if ((weaponClass != k0_WeaponClassSwingWeapon) && (weaponClass < k16_WeaponClassFirstBow)) { +			skillLevel += f303_getSkillLevel(champIndex, k10_ChampionSkillThrow); +		} +		if ((weaponClass >= k16_WeaponClassFirstBow) && (weaponClass < k112_WeaponClassFirstMagicWeapon)) { +			skillLevel += f303_getSkillLevel(champIndex, k11_ChampionSkillShoot); +		} +		strength += skillLevel << 1; +	} +	strength = f306_getStaminaAdjustedValue(curChampion, strength); +	if (getFlag(curChampion->_wounds, (slotIndex == k0_ChampionSlotReadyHand) ? k0x0001_ChampionWoundReadHand : k0x0002_ChampionWoundActionHand)) { +		strength >>= 1; +	} +	return f26_getBoundedValue(0, strength >> 1, 100); +} + +Thing ChampionMan::f300_getObjectRemovedFromSlot(uint16 champIndex, uint16 slotIndex) { +	Champion *curChampion = &_gK71_champions[champIndex]; +	Thing curThing; + +	if (slotIndex >= k30_ChampionSlotChest_1) { +		curThing = _vm->_inventoryMan->_g425_chestSlots[slotIndex - k30_ChampionSlotChest_1]; +		_vm->_inventoryMan->_g425_chestSlots[slotIndex - k30_ChampionSlotChest_1] = Thing::_none; +	} else { +		curThing = curChampion->_slots[slotIndex]; +		curChampion->_slots[slotIndex] = Thing::_none; +	} + +	if (curThing == Thing::_none) +		return Thing::_none; + +	bool isInventoryChampion = (_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal); +	int16 curIconIndex = _vm->_objectMan->f33_getIconIndex(curThing); +	// Remove object modifiers +	f299_applyModifiersToStatistics(curChampion, slotIndex, curIconIndex, -1, curThing); + +	Weapon *curWeapon = (Weapon *)_vm->_dungeonMan->f156_getThingData(curThing); +	if (slotIndex == k10_ChampionSlotNeck) { +		if ((curIconIndex >= k12_IconIndiceJunkIllumuletUnequipped) && (curIconIndex <= k13_IconIndiceJunkIllumuletEquipped)) { +			((Junk *)curWeapon)->setChargeCount(0); +			_g407_party._magicalLightAmount -= g39_LightPowerToLightAmount[2]; +			_vm->_inventoryMan->f337_setDungeonViewPalette(); +		} else if ((curIconIndex >= k10_IconIndiceJunkJewelSymalUnequipped) && (curIconIndex <= k11_IconIndiceJunkJewelSymalEquipped)) { +			((Junk *)curWeapon)->setChargeCount(0); +		} +	} + +	f291_drawSlot(champIndex, slotIndex); +	if (isInventoryChampion) +		setFlag(curChampion->_attributes, k0x4000_ChampionAttributeViewport); + +	if (slotIndex < k2_ChampionSlotHead) { +		if (slotIndex == k1_ChampionSlotActionHand) { +			setFlag(curChampion->_attributes, k0x8000_ChampionAttributeActionHand); +			if (_g506_actingChampionOrdinal == _vm->M0_indexToOrdinal(champIndex)) +				_vm->_menuMan->f388_clearActingChampion(); + +			if ((curIconIndex >= k30_IconIndiceScrollOpen) && (curIconIndex <= k31_IconIndiceScrollClosed)) { +				((Scroll *)curWeapon)->setClosed(true); +				f296_drawChangedObjectIcons(); +			} +		} + +		if ((curIconIndex >= k4_IconIndiceWeaponTorchUnlit) && (curIconIndex <= k7_IconIndiceWeaponTorchLit)) { +			curWeapon->setLit(false); +			_vm->_inventoryMan->f337_setDungeonViewPalette(); +			f296_drawChangedObjectIcons(); +		} + +		if (isInventoryChampion && (slotIndex == k1_ChampionSlotActionHand)) { +			switch (curIconIndex) { +			case k144_IconIndiceContainerChestClosed: +				_vm->_inventoryMan->f334_closeChest(); +			// No break on purpose +			case k30_IconIndiceScrollOpen: +			case k31_IconIndiceScrollClosed: +				setFlag(curChampion->_attributes, k0x0800_ChampionAttributePanel); +				break; +			default: +				break; +			} +		} +	} +	curChampion->_load -= _vm->_dungeonMan->f140_getObjectWeight(curThing); +	setFlag(curChampion->_attributes, k0x0200_ChampionAttributeLoad); +	return curThing; +} + +void ChampionMan::f325_decrementStamina(int16 championIndex, int16 decrement) { +	if (championIndex == kM1_ChampionNone) +		return; + +	Champion *curChampion = &_gK71_champions[championIndex]; +	curChampion->_currStamina -= decrement; + +	int16 stamina = curChampion->_currStamina; +	if (stamina <= 0) { +		curChampion->_currStamina = 0; +		f321_addPendingDamageAndWounds_getDamage(championIndex, (-stamina) >> 1, k0x0000_ChampionWoundNone, k0_attackType_NORMAL); +	} else if (stamina > curChampion->_maxStamina) { +		curChampion->_currStamina = curChampion->_maxStamina; +	} + +	setFlag(curChampion->_attributes, k0x0200_ChampionAttributeLoad | k0x0100_ChampionAttributeStatistics); +} + +int16 ChampionMan::f321_addPendingDamageAndWounds_getDamage(int16 champIndex, int16 attack, int16 allowedWounds, uint16 attackType) { +	if (attack <= 0) +		return 0; + +	Champion *curChampion = &_gK71_champions[champIndex]; +	if (!curChampion->_currHealth) +		return 0; + +	bool skipScaling = false; +	if (attackType != k0_attackType_NORMAL) { +		uint16 defense = 0; +		uint16 woundCount = 0; +		for (int16 woundIndex = k0_ChampionSlotReadyHand; woundIndex <= k5_ChampionSlotFeet; woundIndex++) { +			if (allowedWounds & (1 << woundIndex)) { +				woundCount++; +				defense += f313_getWoundDefense(champIndex, woundIndex | ((attackType == k4_attackType_SHARP) ? k0x8000_maskUseSharpDefense : k0x0000_maskDoNotUseSharpDefense)); +			} +		} +		if (woundCount) +			defense /= woundCount; + +		switch (attackType) { +		case k6_attackType_PSYCHIC: +		{ +			int16 wisdomFactor = 115 - curChampion->_statistics[k3_ChampionStatWisdom][k1_ChampionStatCurrent]; +			if (wisdomFactor <= 0) { +				attack = 0; +			} else { +				attack = _vm->f30_getScaledProduct(attack, 6, wisdomFactor); +			} + +			skipScaling = true; +		} +		break; +		case k5_attackType_MAGIC: +			attack = f307_getStatisticAdjustedAttack(curChampion, k5_ChampionStatAntimagic, attack); +			attack -= _g407_party._spellShieldDefense; +			skipScaling = true; +			break; +		case k1_attackType_FIRE: +			attack = f307_getStatisticAdjustedAttack(curChampion, k6_ChampionStatAntifire, attack); +			attack -= _g407_party._fireShieldDefense; +			break; +		case k2_attackType_SELF: +			defense >>= 1; +			break; +		default: +			break; +		} + +		if (!skipScaling) { +			if (attack <= 0) +				return 0; + +			attack = _vm->f30_getScaledProduct(attack, 6, 130 - defense); +		} +		/* BUG0_44 +			A champion may take much more damage than expected after a Black Flame attack or an impact +			with a Fireball projectile. If the party has a fire shield defense value higher than the fire +			attack value then the resulting intermediary attack value is negative and damage should be 0. +			However, the negative value is still used for further computations and the result may be a very +			high positive attack value which may kill a champion. This can occur only for k1_attackType_FIRE +			and if attack is negative before calling F0030_MAIN_GetScaledProduct +		*/ + +		if (attack <= 0) +			return 0; + +		int16 adjustedAttack = f307_getStatisticAdjustedAttack(curChampion, k4_ChampionStatVitality, _vm->getRandomNumber(128) + 10); +		if (attack > adjustedAttack) { +		/* BUG0_45 +			This bug is not perceptible because of BUG0_41 that ignores Vitality while determining the +			probability of being wounded. However if it was fixed, the behavior would be the opposite +			of what it should: the higher the vitality of a champion, the lower the result of +			F0307_CHAMPION_GetStatisticAdjustedAttack and the more likely the champion could get +			wounded (because of more iterations in the loop below) +		*/ +			do { +				setFlag(*(uint16 *)&_g410_championPendingWounds[champIndex], (1 << _vm->getRandomNumber(8)) & allowedWounds); +			} while ((attack > (adjustedAttack <<= 1)) && adjustedAttack); +		} + +		if (_g300_partyIsSleeping) +			f314_wakeUp(); +	} +	_g409_championPendingDamage[champIndex] += attack; +	return attack; +} + +int16 ChampionMan::f313_getWoundDefense(int16 champIndex, uint16 woundIndex) { +	static const byte woundDefenseFactor[6] = {5, 5, 4, 6, 3, 1}; // @ G0050_auc_Graphic562_WoundDefenseFactor + +	Champion *curChampion = &_gK71_champions[champIndex]; +	bool useSharpDefense = getFlag(woundIndex, k0x8000_maskUseSharpDefense); +	if (useSharpDefense) +		clearFlag(woundIndex, k0x8000_maskUseSharpDefense); + +	uint16 armorShieldDefense = 0; +	for (int16 slotIndex = k0_ChampionSlotReadyHand; slotIndex <= k1_ChampionSlotActionHand; slotIndex++) { +		Thing curThing = curChampion->_slots[slotIndex]; +		if (curThing.getType() == k6_ArmourThingType) { +			ArmourInfo *armorInfo = (ArmourInfo *)_vm->_dungeonMan->f156_getThingData(curThing); +			armorInfo = &g239_ArmourInfo[((Armour *)armorInfo)->getType()]; +			if (getFlag(armorInfo->_attributes, k0x0080_ArmourAttributeIsAShield)) +				armorShieldDefense += ((f312_getStrength(champIndex, slotIndex) + _vm->_dungeonMan->f143_getArmourDefense(armorInfo, useSharpDefense)) * woundDefenseFactor[woundIndex]) >> ((slotIndex == woundIndex) ? 4 : 5); +		} +	} + +	int16 woundDefense = _vm->getRandomNumber((curChampion->_statistics[k4_ChampionStatVitality][k1_ChampionStatCurrent] >> 3) + 1); +	if (useSharpDefense) +		woundDefense >>= 1; + +	woundDefense += curChampion->_actionDefense + curChampion->_shieldDefense + _g407_party._shieldDefense + armorShieldDefense; +	if (woundIndex > k1_ChampionSlotActionHand) { +		Thing curThing = curChampion->_slots[woundIndex]; +		if (curThing.getType() == k6_ArmourThingType) { +			ArmourInfo *armourInfo = (ArmourInfo *)_vm->_dungeonMan->f156_getThingData(curThing); +			woundDefense += _vm->_dungeonMan->f143_getArmourDefense(&g239_ArmourInfo[((Armour *)armourInfo)->getType()], useSharpDefense); +		} +	} + +	if (getFlag(curChampion->_wounds, 1 << woundIndex)) +		woundDefense -= 8 + _vm->getRandomNumber(4); + +	if (_g300_partyIsSleeping) +		woundDefense >>= 1; + +	return f26_getBoundedValue(0, woundDefense >> 1, 100); +} + +uint16 ChampionMan::f307_getStatisticAdjustedAttack(Champion *champ, uint16 statIndex, uint16 attack) { +	int16 factor = 170 - champ->_statistics[statIndex][k1_ChampionStatCurrent]; + +	/* BUG0_41 +		The Antifire and Antimagic statistics are completely ignored. The Vitality statistic is ignored +		against poison and to determine the probability of being wounded. Vitality is still used normally +		to compute the defense against wounds and the speed of health regeneration. A bug in the Megamax C +		compiler produces wrong machine code for this statement. It always returns 0 for the current statistic +		value so that factor = 170 in all cases +	*/ +	if (factor < 16) +		return attack >> 3; + +	return _vm->f30_getScaledProduct(attack, 7, factor); +} + +void ChampionMan::f314_wakeUp() { +	_vm->_g321_stopWaitingForPlayerInput = true; +	_g300_partyIsSleeping = false; +	_vm->_g318_waitForInputMaxVerticalBlankCount = 10; +	_vm->f22_delay(10); +	_vm->_displayMan->f98_drawFloorAndCeiling(); +	_vm->_eventMan->_g441_primaryMouseInput = g447_PrimaryMouseInput_Interface; +	_vm->_eventMan->_g442_secondaryMouseInput = g448_SecondaryMouseInput_Movement; +	_vm->_eventMan->_g443_primaryKeyboardInput = g458_primaryKeyboardInput_interface; +	_vm->_eventMan->_g444_secondaryKeyboardInput = g459_secondaryKeyboardInput_movement; +	_vm->_eventMan->f357_discardAllInput(); +	_vm->_menuMan->f457_drawEnabledMenus(); +} + +int16 ChampionMan::f305_getThrowingStaminaCost(Thing thing) { +	int16 weight = _vm->_dungeonMan->f140_getObjectWeight(thing) >> 1; +	int16 staminaCost = f26_getBoundedValue<int16>(1, weight, 10); + +	while ((weight -= 10) > 0) +		staminaCost += weight >> 1; + +	return staminaCost; +} + +void ChampionMan::f330_disableAction(uint16 champIndex, uint16 ticks) { +	Champion *curChampion = &_gK71_champions[champIndex]; +	int32 updatedEnableActionEventTime = _vm->_g313_gameTime + ticks; + +	TimelineEvent curEvent; +	curEvent._type = k11_TMEventTypeEnableChampionAction; +	curEvent._priority = champIndex; +	curEvent._B._slotOrdinal = 0; + +	int16 eventIndex = curChampion->_enableActionEventIndex; +	if (eventIndex >= 0) { +		int32 currentEnableActionEventTime = M30_time(_vm->_timeline->_g370_events[eventIndex]._mapTime); +		if (updatedEnableActionEventTime >= currentEnableActionEventTime) { +			updatedEnableActionEventTime += (currentEnableActionEventTime - _vm->_g313_gameTime) >> 1; +		} else { +			updatedEnableActionEventTime = currentEnableActionEventTime + (ticks >> 1); +		} +		_vm->_timeline->f237_deleteEvent(eventIndex); +	} else { +		setFlag(curChampion->_attributes, k0x8000_ChampionAttributeActionHand | k0x0008_ChampionAttributeDisableAction); +		f292_drawChampionState((ChampionIndex)champIndex); +	} +	M33_setMapAndTime(curEvent._mapTime, _vm->_dungeonMan->_g309_partyMapIndex, updatedEnableActionEventTime); +	curChampion->_enableActionEventIndex = _vm->_timeline->f238_addEventGetEventIndex(&curEvent); +} + +void ChampionMan::f304_addSkillExperience(uint16 champIndex, uint16 skillIndex, uint16 exp) { +	if ((skillIndex >= k4_ChampionSkillSwing) && (skillIndex <= k11_ChampionSkillShoot) && (_vm->_projexpl->_g361_lastCreatureAttackTime < _vm->_g313_gameTime - 150)) +		exp >>= 1; + +	if (exp) { +		if (_vm->_dungeonMan->_g269_currMap->_difficulty) +			exp *= _vm->_dungeonMan->_g269_currMap->_difficulty; + +		Champion *curChampion = &_gK71_champions[champIndex]; +		uint16 baseSkillIndex; +		if (skillIndex >= k4_ChampionSkillSwing) +			baseSkillIndex = (skillIndex - k4_ChampionSkillSwing) >> 2; +		else +			baseSkillIndex = skillIndex; + +		uint16 skillLevelBefore = f303_getSkillLevel(champIndex, baseSkillIndex | (k0x4000_IgnoreObjectModifiers | k0x8000_IgnoreTemporaryExperience)); + +		if ((skillIndex >= k4_ChampionSkillSwing) && (_vm->_projexpl->_g361_lastCreatureAttackTime > _vm->_g313_gameTime - 25)) +			exp <<= 1; + +		Skill *curSkill = &curChampion->_skills[skillIndex]; +		curSkill->_experience += exp; +		if (curSkill->_temporaryExperience < 32000) +			curSkill->_temporaryExperience += f26_getBoundedValue(1, exp >> 3, 100); + +		curSkill = &curChampion->_skills[baseSkillIndex]; +		if (skillIndex >= k4_ChampionSkillSwing) +			curSkill->_experience += exp; + +		uint16 skillLevelAfter = f303_getSkillLevel(champIndex, baseSkillIndex | (k0x4000_IgnoreObjectModifiers | k0x8000_IgnoreTemporaryExperience)); +		if (skillLevelAfter > skillLevelBefore) { +			int16 newBaseSkillLevel = skillLevelAfter; +			int16 minorStatIncrease = _vm->getRandomNumber(2); +			int16 majorStatIncrease = 1 + _vm->getRandomNumber(2); +			uint16 vitalityAmount = _vm->getRandomNumber(2); /* For Priest skill, the amount is 0 or 1 for all skill levels */ +			if (baseSkillIndex != k2_ChampionSkillPriest) { +				vitalityAmount &= skillLevelAfter; /* For non Priest skills the amount is 0 for even skill levels. The amount is 0 or 1 for odd skill levels */ +			} +			curChampion->_statistics[k4_ChampionStatVitality][k0_ChampionStatMaximum] += vitalityAmount; +			uint16 staminaAmount = curChampion->_maxStamina; +			curChampion->_statistics[k6_ChampionStatAntifire][k0_ChampionStatMaximum] += _vm->getRandomNumber(2) & ~skillLevelAfter; /* The amount is 0 for odd skill levels. The amount is 0 or 1 for even skill levels */ +			bool increaseManaFl = false; +			switch (baseSkillIndex) { +			case k0_ChampionSkillFighter: +				staminaAmount >>= 4; +				skillLevelAfter *= 3; +				curChampion->_statistics[k1_ChampionStatStrength][k0_ChampionStatMaximum] += majorStatIncrease; +				curChampion->_statistics[k2_ChampionStatDexterity][k0_ChampionStatMaximum] += minorStatIncrease; +				break; +			case k1_ChampionSkillNinja: +				staminaAmount /= 21; +				skillLevelAfter <<= 1; +				curChampion->_statistics[k1_ChampionStatStrength][k0_ChampionStatMaximum] += minorStatIncrease; +				curChampion->_statistics[k2_ChampionStatDexterity][k0_ChampionStatMaximum] += majorStatIncrease; +				break; +			case k3_ChampionSkillWizard: +				staminaAmount >>= 5; +				curChampion->_maxMana += skillLevelAfter + (skillLevelAfter >> 1); +				curChampion->_statistics[k3_ChampionStatWisdom][k0_ChampionStatMaximum] += majorStatIncrease; +				increaseManaFl = true; +				break; +			case k2_ChampionSkillPriest: +				staminaAmount /= 25; +				curChampion->_maxMana += skillLevelAfter; +				skillLevelAfter += (skillLevelAfter + 1) >> 1; +				curChampion->_statistics[k3_ChampionStatWisdom][k0_ChampionStatMaximum] += minorStatIncrease; +				increaseManaFl = true; +				break; +			default: +				break; +			} +			if (increaseManaFl) { +				if ((curChampion->_maxMana += MIN(_vm->getRandomNumber(4), (uint16)(newBaseSkillLevel - 1))) > 900) +					curChampion->_maxMana = 900; +				curChampion->_statistics[k5_ChampionStatAntimagic][k0_ChampionStatMaximum] += _vm->getRandomNumber(3); +			} + +			if ((curChampion->_maxHealth += skillLevelAfter + _vm->getRandomNumber((skillLevelAfter >> 1) + 1)) > 999) +				curChampion->_maxHealth = 999; + +			if ((curChampion->_maxStamina += staminaAmount + _vm->getRandomNumber((staminaAmount >> 1) + 1)) > 9999) +				curChampion->_maxStamina = 9999; + +			setFlag(curChampion->_attributes, k0x0100_ChampionAttributeStatistics); +			f292_drawChampionState((ChampionIndex)champIndex); +			_vm->_textMan->f51_messageAreaPrintLineFeed(); +			Color curChampionColor = g46_ChampionColor[champIndex]; +			_vm->_textMan->f47_messageAreaPrintMessage(curChampionColor, curChampion->_name); +			// TODO: localization +			_vm->_textMan->f47_messageAreaPrintMessage(curChampionColor, " JUST GAINED A "); +			_vm->_textMan->f47_messageAreaPrintMessage(curChampionColor, g417_baseSkillName[baseSkillIndex]); +			_vm->_textMan->f47_messageAreaPrintMessage(curChampionColor, " LEVEL!"); +		} +	} +} + +int16 ChampionMan::f324_damageAll_getDamagedChampionCount(uint16 attack, int16 wounds, int16 attackType) { +	int16 randomMax = (attack >> 3) + 1; +	uint16 reducedAttack = attack - randomMax; +	randomMax <<= 1; + +	int16 damagedChampionCount = 0; +	for (int16 championIndex = k0_ChampionFirst; championIndex < _g305_partyChampionCount; championIndex++) { +		// Actual attack is attack +/- (attack / 8) +		if (f321_addPendingDamageAndWounds_getDamage(championIndex, MAX(1, reducedAttack + _vm->getRandomNumber(randomMax)), wounds, attackType)) +			damagedChampionCount++; +	} + +	return damagedChampionCount; +} + +int16 ChampionMan::f286_getTargetChampionIndex(int16 mapX, int16 mapY, uint16 cell) { +	if (_g305_partyChampionCount && (M38_distance(mapX, mapY, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY) <= 1)) { +		signed char orderedCellsToAttack[4]; +		_vm->_groupMan->f229_setOrderedCellsToAttack(orderedCellsToAttack, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY, mapX, mapY, cell); +		for (uint16 i = 0; i < 4; i++) { +			int16 championIndex = f285_getIndexInCell(orderedCellsToAttack[i]); +			if (championIndex >= 0) +				return championIndex; +		} +	} +	return kM1_ChampionNone; +} + +int16 ChampionMan::f311_getDexterity(Champion* champ) { +	int16 dexterity = _vm->getRandomNumber(8) + champ->_statistics[k2_ChampionStatDexterity][k1_ChampionStatCurrent]; +	dexterity -= ((int32)(dexterity >> 1) * (int32)champ->_load) / f309_getMaximumLoad(champ); +	if (_g300_partyIsSleeping) +		dexterity >>= 1; + +	return f26_getBoundedValue(1 + _vm->getRandomNumber(8), dexterity >> 1, 100 - _vm->getRandomNumber(8)); +} + +bool ChampionMan::f308_isLucky(Champion* champ, uint16 percentage) { +	if (_vm->getRandomNumber(2) && (_vm->getRandomNumber(100) > percentage)) +		return true; + +	unsigned char *curStat = champ->_statistics[k0_ChampionStatLuck]; +	bool isLucky = (_vm->getRandomNumber(curStat[k1_ChampionStatCurrent]) > percentage); +	curStat[k1_ChampionStatCurrent] = f26_getBoundedValue<char>(curStat[k2_ChampionStatMinimum], curStat[k1_ChampionStatCurrent] + (isLucky ? -2 : 2), curStat[k0_ChampionStatMaximum]); +	return isLucky; +} + +void ChampionMan::f322_championPoison(int16 champIndex, uint16 attack) { +	if ((champIndex == kM1_ChampionNone) || (_vm->M0_indexToOrdinal(champIndex) == _g299_candidateChampionOrdinal)) +		return; + +	Champion *curChampion = &_gK71_champions[champIndex]; +	f321_addPendingDamageAndWounds_getDamage(champIndex, MAX(1, attack >> 6), k0x0000_ChampionWoundNone, k0_attackType_NORMAL); +	setFlag(curChampion->_attributes, k0x0100_ChampionAttributeStatistics); +	if ((_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) && (_vm->_inventoryMan->_g424_panelContent == k0_PanelContentFoodWaterPoisoned)) { +		setFlag(curChampion->_attributes, k0x0800_ChampionAttributePanel); +	} + +	if (--attack) { +		curChampion->_poisonEventCount++; +		TimelineEvent newEvent; +		newEvent._type = k75_TMEventTypePoisonChampion; +		newEvent._priority = champIndex; +		M33_setMapAndTime(newEvent._mapTime, _vm->_dungeonMan->_g309_partyMapIndex, _vm->_g313_gameTime + 36); +		newEvent._B._attack = attack; +		_vm->_timeline->f238_addEventGetEventIndex(&newEvent); +	} + +	f292_drawChampionState((ChampionIndex)champIndex); +} + +void ChampionMan::f284_setPartyDirection(int16 dir) { +	if (dir == _vm->_dungeonMan->_g308_partyDir) +		return; + +	int16 L0834_i_Delta = dir - _vm->_dungeonMan->_g308_partyDir; +	if (L0834_i_Delta < 0) +		L0834_i_Delta += 4; + +	Champion *curChampion = _gK71_champions; +	for (int16 i = k0_ChampionFirst; i < _g305_partyChampionCount; i++) { +		curChampion->_cell = (ViewCell)M21_normalizeModulo4(curChampion->_cell + L0834_i_Delta); +		curChampion->_dir = (Direction)M21_normalizeModulo4(curChampion->_dir + L0834_i_Delta); +		curChampion++; +	} + +	_vm->_dungeonMan->_g308_partyDir = (Direction)dir; +	f296_drawChangedObjectIcons(); +} + +void ChampionMan::f316_deleteScent(uint16 scentIndex) { +	uint16 count = --_g407_party._scentCount - scentIndex; + +	if (count) { +		for (uint16 i = 0; i < count; ++i) { +			_g407_party._scents[scentIndex + i] = _g407_party._scents[scentIndex + i + 1]; +			_g407_party._scentStrengths[scentIndex + i] = _g407_party._scentStrengths[scentIndex + i + 1]; +		} +	} + +	if (scentIndex < _g407_party._firstScentIndex) +		_g407_party._firstScentIndex--; + +	if (scentIndex < _g407_party._lastScentIndex) +		_g407_party._lastScentIndex--; +} + +void ChampionMan::f317_addScentStrength(int16 mapX, int16 mapY, int32 cycleCount) { +	int16 scentIndex = _g407_party._scentCount; +	if (scentIndex) { +		bool mergeFl = getFlag(cycleCount, k0x8000_mergeCycles); +		if (mergeFl) +			clearFlag(cycleCount, k0x8000_mergeCycles); + +		Scent newScent; /* BUG0_00 Useless code */ +		newScent.setMapX(mapX); /* BUG0_00 Useless code */ +		newScent.setMapY(mapY); /* BUG0_00 Useless code */ +		newScent.setMapIndex(_vm->_dungeonMan->_g272_currMapIndex); /* BUG0_00 Useless code */ + +		Scent *curScent = _g407_party._scents; /* BUG0_00 Useless code */ +		bool cycleCountDefined = false; +		while (scentIndex--) { +			if (&*curScent++ == &newScent) { +				if (!cycleCountDefined) { +					cycleCountDefined = true; +					if (mergeFl) { +						cycleCount = MAX<int32>(_g407_party._scentStrengths[scentIndex], cycleCount); +					} else { +						cycleCount = MIN<int32>(80, _g407_party._scentStrengths[scentIndex] + cycleCount); +					} +				} +				_g407_party._scentStrengths[scentIndex] = cycleCount; +			} +		} +	} +} + +void ChampionMan::f297_putObjectInLeaderHand(Thing thing, bool setMousePointer) { +	if (thing == Thing::_none) +		return; + +	_g415_leaderEmptyHanded = false; +	_vm->_objectMan->f36_extractIconFromBitmap(_g413_leaderHandObjectIconIndex = _vm->_objectMan->f33_getIconIndex(_g414_leaderHandObject = thing), _vm->_objectMan->_g412_objectIconForMousePointer); +	_vm->_eventMan->f78_showMouse(); +	_vm->_objectMan->f34_drawLeaderObjectName(thing); + +	if (setMousePointer) +		_vm->_g325_setMousePointerToObjectInMainLoop = true; +	else +		_vm->_eventMan->f68_setPointerToObject(_vm->_objectMan->_g412_objectIconForMousePointer); + +	_vm->_eventMan->f77_hideMouse(); +	if (_g411_leaderIndex != kM1_ChampionNone) { +		_gK71_champions[_g411_leaderIndex]._load += _vm->_dungeonMan->f140_getObjectWeight(thing); +		setFlag(_gK71_champions[_g411_leaderIndex]._attributes, k0x0200_ChampionAttributeLoad); +		f292_drawChampionState(_g411_leaderIndex); +	} +} + +int16 ChampionMan::f310_getMovementTicks(Champion *champ) { +	uint16 maximumLoad = f309_getMaximumLoad(champ); +	uint16 curLoad = champ->_load; +	uint16 woundTicks; +	int16 ticks; +	/* BUG0_72 - Fixed +		The party moves very slowly even though no champion 'Load' value is drawn in red. +		When the Load of a champion has exactly the maximum value he can carry then the Load +		is drawn in yellow but the speed is the same as when the champion is overloaded +		(when the Load is drawn in red). The comparison operator should be >= instead of > +	*/ +	if (maximumLoad >= curLoad) { +		ticks = 2; +		if (((int32)curLoad << 3) > ((int32)maximumLoad * 5)) +			ticks++; + +		woundTicks = 1; +	} else { +		ticks = 4 + (((curLoad - maximumLoad) << 2) / maximumLoad); +		woundTicks = 2; +	} + +	if (getFlag(champ->_wounds, k0x0020_ChampionWoundFeet)) +		ticks += woundTicks; + +	if (_vm->_objectMan->f33_getIconIndex(champ->_slots[k5_ChampionSlotFeet]) == k194_IconIndiceArmourBootOfSpeed) +		ticks--; + +	return ticks; +} + +bool ChampionMan::f294_isAmmunitionCompatibleWithWeapon(uint16 champIndex, uint16 weaponSlotIndex, uint16 ammunitionSlotIndex) { +	Champion *curChampion = &_gK71_champions[champIndex]; +	Thing curThing = curChampion->_slots[weaponSlotIndex]; +	if (curThing.getType() != k5_WeaponThingType) +		return false; + +	WeaponInfo *weaponInfo = _vm->_dungeonMan->f158_getWeaponInfo(curThing); +	int16 weaponClass = kM1_WeaponClassNone; + +	if ((weaponInfo->_class >= k16_WeaponClassFirstBow) && (weaponInfo->_class <= k31_WeaponClassLastBow)) +		weaponClass = k10_WeaponClassBowAmmunition; +	else if ((weaponInfo->_class >= k32_WeaponClassFirstSling) && (weaponInfo->_class <= k47_WeaponClassLastSling)) +		weaponClass = k11_WeaponClassSlingAmmunition; + +	if (weaponClass == kM1_WeaponClassNone) +		return false; + +	curThing = curChampion->_slots[ammunitionSlotIndex]; +	weaponInfo = _vm->_dungeonMan->f158_getWeaponInfo(curThing); +	return ((curThing.getType() == k5_WeaponThingType) && (weaponInfo->_class == weaponClass)); +} + +void ChampionMan::f293_drawAllChampionStates() { +	for (int16 i = k0_ChampionFirst; i < _g305_partyChampionCount; i++) +		f292_drawChampionState((ChampionIndex)i); +} + +void ChampionMan::f283_viAltarRebirth(uint16 champIndex) { +	Champion *curChampion = &_gK71_champions[champIndex]; +	if (f285_getIndexInCell(curChampion->_cell) != kM1_ChampionNone) { +		uint16 numCell = k0_CellNorthWest; +		while (f285_getIndexInCell(numCell) != kM1_ChampionNone) +			numCell++; + +		curChampion->_cell = (ViewCell)numCell; +	} + +	uint16 maximumHealth = curChampion->_maxHealth; +	curChampion->_maxHealth = MAX(25, maximumHealth - (maximumHealth >> 6) - 1); +	curChampion->_currHealth = curChampion->_maxHealth >> 1; +	_vm->_menuMan->f393_drawSpellAreaControls(_g514_magicCasterChampionIndex); +	curChampion->_dir = _vm->_dungeonMan->_g308_partyDir; +	setFlag(curChampion->_attributes, k0x8000_ChampionAttributeActionHand | k0x1000_ChampionAttributeStatusBox | k0x0400_ChampionAttributeIcon); +	f292_drawChampionState((ChampionIndex)champIndex); +} + +void ChampionMan::f302_processCommands28to65_clickOnSlotBox(uint16 slotBoxIndex) { +	uint16 champIndex; +	uint16 slotIndex; + +	if (slotBoxIndex < k8_SlotBoxInventoryFirstSlot) { +		if (_g299_candidateChampionOrdinal) +			return; + +		champIndex = slotBoxIndex >> 1; +		if ((champIndex >= _g305_partyChampionCount) || (_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) || !_gK71_champions[champIndex]._currHealth) +			return; + +		slotIndex = M70_handSlotIndex(slotBoxIndex); +	} else { +		champIndex = _vm->M1_ordinalToIndex(_vm->_inventoryMan->_g432_inventoryChampionOrdinal); +		slotIndex = slotBoxIndex - k8_SlotBoxInventoryFirstSlot; +	} + +	Thing leaderHandObject = _g414_leaderHandObject; +	Thing slotThing; +	if (slotIndex >= k30_ChampionSlotChest_1) { +		slotThing = _vm->_inventoryMan->_g425_chestSlots[slotIndex - k30_ChampionSlotChest_1]; +	} else { +		slotThing = _gK71_champions[champIndex]._slots[slotIndex]; +	} + +	if ((slotThing == Thing::_none) && (leaderHandObject == Thing::_none)) +		return; + +	if ((leaderHandObject != Thing::_none) && (!(g237_ObjectInfo[_vm->_dungeonMan->f141_getObjectInfoIndex(leaderHandObject)]._allowedSlots & gSlotMasks[slotIndex]))) +		return; + +	_vm->_eventMan->f78_showMouse(); +	if (leaderHandObject != Thing::_none) +		f298_getObjectRemovedFromLeaderHand(); + +	if (slotThing != Thing::_none) { +		f300_getObjectRemovedFromSlot(champIndex, slotIndex); +		f297_putObjectInLeaderHand(slotThing, false); +	} + +	if (leaderHandObject != Thing::_none) +		f301_addObjectInSlot((ChampionIndex)champIndex, leaderHandObject, (ChampionSlot)slotIndex); + +	f292_drawChampionState((ChampionIndex)champIndex); +	_vm->_eventMan->f77_hideMouse(); +} + +bool ChampionMan::f327_isProjectileSpellCast(uint16 champIndex, Thing thing, int16 kineticEnergy, uint16 requiredManaAmount) { +	Champion *curChampion = &_gK71_champions[champIndex]; +	if (curChampion->_currMana < requiredManaAmount) +		return false; + +	curChampion->_currMana -= requiredManaAmount; +	setFlag(curChampion->_attributes, k0x0100_ChampionAttributeStatistics); +	int16 stepEnergy = 10 - MIN(8, curChampion->_maxMana >> 3); +	if (kineticEnergy < (stepEnergy << 2)) { +		kineticEnergy += 3; +		stepEnergy--; +	} + +	f326_championShootProjectile(curChampion, thing, kineticEnergy, 90, stepEnergy); +	return true; // fix BUG_01 +} + +void ChampionMan::f326_championShootProjectile(Champion* champ, Thing thing, int16 kineticEnergy, int16 attack, int16 stepEnergy) { +	Direction newDirection = champ->_dir; +	_vm->_projexpl->f212_projectileCreate(thing, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY, M21_normalizeModulo4((((champ->_cell - newDirection + 1) & 0x0002) >> 1) + newDirection), newDirection, kineticEnergy, attack, stepEnergy); +	_vm->_g311_projectileDisableMovementTicks = 4; +	_vm->_g312_lastProjectileDisabledMovementDirection = newDirection; +} + +void ChampionMan::f320_applyAndDrawPendingDamageAndWounds() { +	Champion *championPtr = _gK71_champions; +	for (uint16 championIndex = k0_ChampionFirst; championIndex < _g305_partyChampionCount; championIndex++, championPtr++) { +		int16 pendingWounds = _g410_championPendingWounds[championIndex]; +		setFlag(championPtr->_wounds, pendingWounds); +		_g410_championPendingWounds[championIndex] = 0; +		uint16 pendingDamage = _g409_championPendingDamage[championIndex]; +		if (!pendingDamage) +			continue; + +		_g409_championPendingDamage[championIndex] = 0; +		int16 curHealth = championPtr->_currHealth; +		if (!curHealth) +			continue; + +		// DEBUG CODE +		if (_vm->_console->_debugGodmodeHP == false) +			curHealth -= pendingDamage; + +		if (curHealth <= 0) { +			f319_championKill(championIndex); +		} else { +			championPtr->_currHealth = curHealth; +			setFlag(championPtr->_attributes, k0x0100_ChampionAttributeStatistics); +			if (pendingWounds) { +				setFlag(championPtr->_attributes, k0x2000_ChampionAttributeWounds); +			} + +			int16 textPosX = championIndex * k69_ChampionStatusBoxSpacing; +			int16 textPosY; + +			Box blitBox; +			blitBox._y1 = 0; +			_vm->_eventMan->f78_showMouse(); + +			if (_vm->M0_indexToOrdinal(championIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) { +				blitBox._y2 = 28; +				blitBox._x1 = textPosX + 7; +				blitBox._x2 = blitBox._x1 + 31; /* Box is over the champion portrait in the status box */ +				_vm->_displayMan->f21_blitToScreen(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k16_damageToChampionBig), &blitBox, k16_byteWidth, k10_ColorFlesh, 29); +				// Check the number of digits and sets the position accordingly. +				if (pendingDamage < 10) // 1 digit +					textPosX += 21; +				else if (pendingDamage < 100)  // 2 digits +					textPosX += 18; +				else // 3 digits +					textPosX += 15; + +				textPosY = 16; +			} else { +				blitBox._y2 = 6; +				blitBox._x1 = textPosX; +				blitBox._x2 = blitBox._x1 + 47; /* Box is over the champion name in the status box */ +				_vm->_displayMan->f21_blitToScreen(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k15_damageToChampionSmallIndice), &blitBox, k24_byteWidth, k10_ColorFlesh, 7); +				// Check the number of digits and sets the position accordingly. +				if (pendingDamage < 10) // 1 digit +					textPosX += 19; +				else if (pendingDamage < 100) // 2 digits +					textPosX += 16; +				else //3 digits +					textPosX += 13; + +				textPosY = 5; +			} +			_vm->_textMan->f53_printToLogicalScreen(textPosX, textPosY, k15_ColorWhite, k8_ColorRed, f288_getStringFromInteger(pendingDamage, false, 3).c_str()); + +			int16 eventIndex = championPtr->_hideDamageReceivedIndex; +			if (eventIndex == -1) { +				TimelineEvent newEvent; +				newEvent._type = k12_TMEventTypeHideDamageReceived; +				M33_setMapAndTime(newEvent._mapTime, _vm->_dungeonMan->_g309_partyMapIndex, _vm->_g313_gameTime + 5); +				newEvent._priority = championIndex; +				championPtr->_hideDamageReceivedIndex = _vm->_timeline->f238_addEventGetEventIndex(&newEvent); +			} else { +				TimelineEvent *curEvent = &_vm->_timeline->_g370_events[eventIndex]; +				M33_setMapAndTime(curEvent->_mapTime, _vm->_dungeonMan->_g309_partyMapIndex, _vm->_g313_gameTime + 5); +				_vm->_timeline->f236_fixChronology(_vm->_timeline->f235_getIndex(eventIndex)); +			} +			f292_drawChampionState((ChampionIndex)championIndex); +			_vm->_eventMan->f77_hideMouse(); +		} +	} +} + +void ChampionMan::f319_championKill(uint16 champIndex) { +	Champion *curChampion = &_gK71_champions[champIndex]; +	curChampion->_currHealth = 0; +	setFlag(curChampion->_attributes, k0x1000_ChampionAttributeStatusBox); +	if (_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) { +		if (_vm->_g331_pressingEye) { +			_vm->_g331_pressingEye = false; +			_vm->_eventMan->_g597_ignoreMouseMovements = false; +			if (!_g415_leaderEmptyHanded) { +				_vm->_objectMan->f34_drawLeaderObjectName(_g414_leaderHandObject); +			} +			_vm->_eventMan->_g587_hideMousePointerRequestCount = 1; +			_vm->_eventMan->f77_hideMouse(); +		} else if (_vm->_g333_pressingMouth) { +			_vm->_g333_pressingMouth = false; +			_vm->_eventMan->_g597_ignoreMouseMovements = false; +			_vm->_eventMan->_g587_hideMousePointerRequestCount = 1; +			_vm->_eventMan->f77_hideMouse(); +		} +		_vm->_inventoryMan->f355_toggleInventory(k4_ChampionCloseInventory); +	} +	f318_dropAllObjects(champIndex); +	Thing unusedThing = _vm->_dungeonMan->f166_getUnusedThing(k0x8000_championBones | k10_JunkThingType); +	uint16 curCell = 0; +	if (unusedThing != Thing::_none) { +		Junk *L0966_ps_Junk = (Junk *)_vm->_dungeonMan->f156_getThingData(unusedThing); +		L0966_ps_Junk->setType(k5_JunkTypeBones); +		L0966_ps_Junk->setDoNotDiscard(true); +		L0966_ps_Junk->setChargeCount(champIndex); +		curCell = curChampion->_cell; +		_vm->_moveSens->f267_getMoveResult(M15_thingWithNewCell(unusedThing, curCell), kM1_MapXNotOnASquare, 0, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY); +	} +	curChampion->_symbolStep = 0; +	curChampion->_symbols[0] = '\0'; +	curChampion->_dir = _vm->_dungeonMan->_g308_partyDir; +	curChampion->_maximumDamageReceived = 0; +	uint16 curChampionIconIndex = M26_championIconIndex(curCell, _vm->_dungeonMan->_g308_partyDir); +	if (_vm->M0_indexToOrdinal(curChampionIconIndex) == _vm->_eventMan->_g599_useChampionIconOrdinalAsMousePointerBitmap) { +		_vm->_eventMan->_g598_mousePointerBitmapUpdated = true; +		_vm->_eventMan->_g599_useChampionIconOrdinalAsMousePointerBitmap = _vm->M0_indexToOrdinal(kM1_ChampionNone); +		warning(false, "IGNORED CODE:G0592_B_BuildMousePointerScreenAreaRequested = true"); +	} + +	if (curChampion->_poisonEventCount) +		f323_unpoison(champIndex); + +	_vm->_displayMan->_g578_useByteBoxCoordinates = false; +	_vm->_displayMan->D24_fillScreenBox(g54_BoxChampionIcons[curChampionIconIndex << 2], k0_ColorBlack); +	f292_drawChampionState((ChampionIndex)champIndex); + +	int16 aliveChampionIndex; +	for (aliveChampionIndex = k0_ChampionFirst, curChampion = _gK71_champions; aliveChampionIndex < _g305_partyChampionCount; aliveChampionIndex++, curChampion++) { +		if (curChampion->_currHealth) +			break; +	} + +	if (aliveChampionIndex == _g305_partyChampionCount) { /* BUG0_43 The game does not end if the last living champion in the party is killed while looking at a candidate champion in a portrait. The condition to end the game when the whole party is killed is not true because the code considers the candidate champion as alive (in the loop above) */ +		_g303_partyDead = true; +		return; +	} + +	if (champIndex == _g411_leaderIndex) +		_vm->_eventMan->f368_commandSetLeader((ChampionIndex)aliveChampionIndex); + +	if (champIndex == _g514_magicCasterChampionIndex) +		_vm->_menuMan->f394_setMagicCasterAndDrawSpellArea(aliveChampionIndex); +	else +		_vm->_menuMan->f393_drawSpellAreaControls(_g514_magicCasterChampionIndex); +} + +void ChampionMan::f318_dropAllObjects(uint16 champIndex) { +	static const int16 slotDropOrder[30] = { +		k5_ChampionSlotFeet, +		k4_ChampionSlotLegs, +		k9_ChampionSlotQuiverLine_2_2, +		k8_ChampionSlotQuiverLine_1_2, +		k7_ChampionSlotQuiverLine_2_1, +		k12_ChampionSlotQuiverLine_1_1, +		k6_ChampionSlotPouch_2, +		k11_ChampionSlotPouch_1, +		k3_ChampionSlotTorso, +		k13_ChampionSlotBackpackLine_1_1, +		k14_ChampionSlotBackpackLine_2_2, +		k15_ChampionSlotBackpackLine_2_3, +		k16_ChampionSlotBackpackLine_2_4, +		k17_ChampionSlotBackpackLine_2_5, +		k18_ChampionSlotBackpackLine_2_6, +		k19_ChampionSlotBackpackLine_2_7, +		k20_ChampionSlotBackpackLine_2_8, +		k21_ChampionSlotBackpackLine_2_9, +		k22_ChampionSlotBackpackLine_1_2, +		k23_ChampionSlotBackpackLine_1_3, +		k24_ChampionSlotBackpackLine_1_4, +		k25_ChampionSlotBackpackLine_1_5, +		k26_ChampionSlotBackpackLine_1_6, +		k27_ChampionSlotBackpackLine_1_7, +		k28_ChampionSlotBackpackLine_1_8, +		k29_ChampionSlotBackpackLine_1_9, +		k10_ChampionSlotNeck, +		k2_ChampionSlotHead, +		k0_ChampionSlotReadyHand, +		k1_ChampionSlotActionHand +	}; + +	uint16 curCell = _gK71_champions[champIndex]._cell; +	for (uint16 slotIndex = k0_ChampionSlotReadyHand; slotIndex < k30_ChampionSlotChest_1; slotIndex++) { +		Thing curThing = f300_getObjectRemovedFromSlot(champIndex, slotDropOrder[slotIndex]); +		if (curThing != Thing::_none) +			_vm->_moveSens->f267_getMoveResult(M15_thingWithNewCell(curThing, curCell), kM1_MapXNotOnASquare, 0, _vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY); +	} +} + +void ChampionMan::f323_unpoison(int16 champIndex) { +	if (champIndex == kM1_ChampionNone) +		return; + +	TimelineEvent *eventPtr = _vm->_timeline->_g370_events; +	for (uint16 eventIndex = 0; eventIndex < _vm->_timeline->_g369_eventMaxCount; eventPtr++, eventIndex++) { +		if ((eventPtr->_type == k75_TMEventTypePoisonChampion) && (eventPtr->_priority == champIndex)) +			_vm->_timeline->f237_deleteEvent(eventIndex); +	} +	_gK71_champions[champIndex]._poisonEventCount = 0; +} + +void ChampionMan::f331_applyTimeEffects() { +	if (!_g305_partyChampionCount) +		return; + +	Scent checkScent; +	checkScent.setMapX(_vm->_dungeonMan->_g306_partyMapX); +	checkScent.setMapY(_vm->_dungeonMan->_g307_partyMapY); +	checkScent.setMapIndex(_vm->_dungeonMan->_g309_partyMapIndex); + +	for (byte loopScentIndex = 0; loopScentIndex + 1 < _g407_party._scentCount; loopScentIndex++) { +		if (&_g407_party._scents[loopScentIndex] != &checkScent) { +			_g407_party._scentStrengths[loopScentIndex] = MAX(0, _g407_party._scentStrengths[loopScentIndex] - 1); +			if (!_g407_party._scentStrengths[loopScentIndex] && !loopScentIndex) { +				f316_deleteScent(0); +				continue; +			} +		} +	} + +	uint16 gameTime = _vm->_g313_gameTime & 0xFFFF; +	uint16 timeCriteria = (((gameTime & 0x0080) + ((gameTime & 0x0100) >> 2)) + ((gameTime & 0x0040) << 2)) >> 2; +	Champion *championPtr = _gK71_champions; +	for (uint16 championIndex = k0_ChampionFirst; championIndex < _g305_partyChampionCount; championIndex++, championPtr++) { +		if (championPtr->_currHealth && (_vm->M0_indexToOrdinal(championIndex) != _g299_candidateChampionOrdinal)) { +			uint16 wizardSkillLevel = f303_getSkillLevel(championIndex, k3_ChampionSkillWizard) + f303_getSkillLevel(championIndex, k2_ChampionSkillPriest); +			if ((championPtr->_currMana < championPtr->_maxMana) +				&& (timeCriteria < championPtr->_statistics[k3_ChampionStatWisdom][k1_ChampionStatCurrent] + wizardSkillLevel)) { +				int16 manaGain = championPtr->_maxMana / 40; +				if (_g300_partyIsSleeping) +					manaGain <<= 1; + +				manaGain++; +				f325_decrementStamina(championIndex, manaGain * MAX(7, 16 - wizardSkillLevel)); +				championPtr->_currMana += MIN<int16>(manaGain, championPtr->_maxMana - championPtr->_currMana); +			} else if (championPtr->_currMana > championPtr->_maxMana) +				championPtr->_currMana--; + +			for (int16 idx = k19_ChampionSkillWater; idx >= k0_ChampionSkillFighter; idx--) { +				if (championPtr->_skills[idx]._temporaryExperience > 0) +					championPtr->_skills[idx]._temporaryExperience--; +			} +			uint16 staminaGainCycleCount = 4; +			int16 staminaMagnitude = championPtr->_maxStamina; +			while (championPtr->_currStamina < (staminaMagnitude >>= 1)) +				staminaGainCycleCount += 2; + +			int16 staminaLoss = 0; +			int16 staminaAmount = f26_getBoundedValue(1, (championPtr->_maxStamina >> 8) - 1, 6); +			if (_g300_partyIsSleeping) +				staminaAmount <<= 1; + +			int32 compDelay = _vm->_g313_gameTime - _vm->_projexpl->_g362_lastPartyMovementTime; +			if (compDelay > 80) { +				staminaAmount++; +				if (compDelay > 250) +					staminaAmount++; +			} +			do { +				bool staminaAboveHalf = (staminaGainCycleCount <= 4); +				if (championPtr->_food < -512) { +					if (staminaAboveHalf) { +						staminaLoss += staminaAmount; +						championPtr->_food -= 2; +					} +				} else { +					if (championPtr->_food >= 0) +						staminaLoss -= staminaAmount; + +					championPtr->_food -= staminaAboveHalf ? 2 : staminaGainCycleCount >> 1; +				} +				if (championPtr->_water < -512) { +					if (staminaAboveHalf) { +						staminaLoss += staminaAmount; +						championPtr->_water -= 1; +					} +				} else { +					if (championPtr->_water >= 0) +						staminaLoss -= staminaAmount; + +					championPtr->_water -= staminaAboveHalf ? 1 : staminaGainCycleCount >> 2; +				} +			} while (--staminaGainCycleCount && ((championPtr->_currStamina - staminaLoss) < championPtr->_maxStamina)); +			f325_decrementStamina(championIndex, staminaLoss); +			if (championPtr->_food < -1024) +				championPtr->_food = -1024; + +			if (championPtr->_water < -1024) +				championPtr->_water = -1024; + +			if ((championPtr->_currHealth < championPtr->_maxHealth) && (championPtr->_currStamina >= (championPtr->_maxStamina >> 2)) && (timeCriteria < (championPtr->_statistics[k4_ChampionStatVitality][k1_ChampionStatCurrent] + 12))) { +				int16 healthGain = (championPtr->_maxHealth >> 7) + 1; +				if (_g300_partyIsSleeping) +					healthGain <<= 1; + +				if (_vm->_objectMan->f33_getIconIndex(championPtr->_slots[k10_ChampionSlotNeck]) == k121_IconIndiceJunkEkkhardCross) +					healthGain += (healthGain >> 1) + 1; + +				championPtr->_currHealth += MIN(healthGain, (int16)(championPtr->_maxHealth - championPtr->_currHealth)); +			} +			if (!((int)_vm->_g313_gameTime & (_g300_partyIsSleeping ? 63 : 255))) { +				for (uint16 i = k0_ChampionStatLuck; i <= k6_ChampionStatAntifire; i++) { +					byte *curStatistic = championPtr->_statistics[i]; +					uint16 statisticMaximum = curStatistic[k0_ChampionStatMaximum]; +					if (curStatistic[k1_ChampionStatCurrent] < statisticMaximum) +						curStatistic[k1_ChampionStatCurrent]++; +					else if (curStatistic[k1_ChampionStatCurrent] > statisticMaximum) +						curStatistic[k1_ChampionStatCurrent] -= curStatistic[k1_ChampionStatCurrent] / statisticMaximum; +				} +			} +			if (!_g300_partyIsSleeping && (championPtr->_dir != _vm->_dungeonMan->_g308_partyDir) && (_vm->_projexpl->_g361_lastCreatureAttackTime + 60 < _vm->_g313_gameTime)) { +				championPtr->_dir = _vm->_dungeonMan->_g308_partyDir; +				championPtr->_maximumDamageReceived = 0; +				setFlag(championPtr->_attributes, k0x0400_ChampionAttributeIcon); +			} +			setFlag(championPtr->_attributes, k0x0100_ChampionAttributeStatistics); +			if (_vm->M0_indexToOrdinal(championIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal) { +				if (_vm->_g333_pressingMouth || _vm->_g331_pressingEye || (_vm->_inventoryMan->_g424_panelContent == k0_PanelContentFoodWaterPoisoned)) { +					setFlag(championPtr->_attributes, k0x0800_ChampionAttributePanel); +				} +			} +		} +	} +	f293_drawAllChampionStates(); +} + +void ChampionMan::save2_PartyPart(Common::OutSaveFile* file) { +	for (uint16 i = 0; i < 4; ++i) { +		Champion *champ = &_gK71_champions[i]; +		file->writeUint16BE(champ->_attributes); +		file->writeUint16BE(champ->_wounds); +		for (uint16 y = 0; y < 7; ++y) +			for (uint16 x = 0; x < 3; ++x) +				file->writeByte(champ->_statistics[y][x]); +		for (uint16 j = 0; j < 30; ++j) +			file->writeUint16BE(champ->_slots[j].toUint16()); +		for (uint16 j = 0; j < 20; ++j) { +			file->writeSint16BE(champ->_skills[j]._temporaryExperience); +			file->writeSint32BE(champ->_skills[j]._experience); +		} +		for (uint16 j = 0; j < 8; ++j) +			file->writeByte(champ->_name[j]); +		for (uint16 j = 0; j < 20; ++j) +			file->writeByte(champ->_title[j]); +		file->writeUint16BE(champ->_dir); +		file->writeUint16BE(champ->_cell); +		file->writeUint16BE(champ->_actionIndex); +		file->writeUint16BE(champ->_symbolStep); +		for (uint16 j = 0; j < 5; ++j) +			file->writeByte(champ->_symbols[j]); +		file->writeUint16BE(champ->_directionMaximumDamageReceived); +		file->writeUint16BE(champ->_maximumDamageReceived); +		file->writeUint16BE(champ->_poisonEventCount); +		file->writeSint16BE(champ->_enableActionEventIndex); +		file->writeSint16BE(champ->_hideDamageReceivedIndex); +		file->writeSint16BE(champ->_currHealth); +		file->writeSint16BE(champ->_maxHealth); +		file->writeSint16BE(champ->_currStamina); +		file->writeSint16BE(champ->_maxStamina); +		file->writeSint16BE(champ->_currMana); +		file->writeSint16BE(champ->_maxMana); +		file->writeSint16BE(champ->_actionDefense); +		file->writeSint16BE(champ->_food); +		file->writeSint16BE(champ->_water); +		file->writeUint16BE(champ->_load); +		file->writeSint16BE(champ->_shieldDefense); +		for (uint16 j = 0; j < 928; ++j) +			file->writeByte(champ->_portrait[j]); +	} + +	Party &party = _g407_party; +	file->writeSint16BE(party._magicalLightAmount); +	file->writeByte(party._event73Count_ThievesEye); +	file->writeByte(party._event79Count_Footprints); +	file->writeSint16BE(party._shieldDefense); +	file->writeSint16BE(party._fireShieldDefense); +	file->writeSint16BE(party._spellShieldDefense); +	file->writeByte(party._scentCount); +	file->writeByte(party._freezeLifeTicks); +	file->writeByte(party._firstScentIndex); +	file->writeByte(party._lastScentIndex); +	for (uint16 i = 0; i < 24; ++i) +		file->writeUint16BE(party._scents[i].toUint16()); +	for (uint16 i = 0; i < 24; ++i) +		file->writeByte(party._scentStrengths[i]); +	file->writeByte(party._event71Count_Invisibility); +} + +void ChampionMan::load2_PartyPart(Common::InSaveFile* file) { +	for (uint16 i = 0; i < 4; ++i) { +		Champion *champ = &_gK71_champions[i]; +		champ->_attributes = file->readUint16BE(); +		champ->_wounds = file->readUint16BE(); +		for (uint16 y = 0; y < 7; ++y) +			for (uint16 x = 0; x < 3; ++x) +				champ->_statistics[y][x] = file->readByte(); +		for (uint16 j = 0; j < 30; ++j) +			champ->_slots[j] = Thing(file->readUint16BE()); +		for (uint16 j = 0; j < 20; ++j) { +			champ->_skills[j]._temporaryExperience = file->readSint16BE(); +			champ->_skills[j]._experience = file->readSint32BE(); +		} +		for (uint16 j = 0; j < 8; ++j) +			champ->_name[j] = file->readByte(); +		for (uint16 j = 0; j < 20; ++j) +			champ->_title[j] = file->readByte(); +		champ->_dir = (Direction)file->readUint16BE(); +		champ->_cell = (ViewCell)file->readUint16BE(); +		champ->_actionIndex = (ChampionAction)file->readUint16BE(); +		champ->_symbolStep = file->readUint16BE(); +		for (uint16 j = 0; j < 5; ++j) +			champ->_symbols[j] = file->readByte(); +		champ->_directionMaximumDamageReceived = file->readUint16BE(); +		champ->_maximumDamageReceived = file->readUint16BE(); +		champ->_poisonEventCount = file->readUint16BE(); +		champ->_enableActionEventIndex = file->readSint16BE(); +		champ->_hideDamageReceivedIndex = file->readSint16BE(); +		champ->_currHealth = file->readSint16BE(); +		champ->_maxHealth = file->readSint16BE(); +		champ->_currStamina = file->readSint16BE(); +		champ->_maxStamina = file->readSint16BE(); +		champ->_currMana = file->readSint16BE(); +		champ->_maxMana = file->readSint16BE(); +		champ->_actionDefense = file->readSint16BE(); +		champ->_food = file->readSint16BE(); +		champ->_water = file->readSint16BE(); +		champ->_load = file->readUint16BE(); +		champ->_shieldDefense = file->readSint16BE(); +		for (uint16 j = 0; j < 928; ++j) +			champ->_portrait[j] = file->readByte(); +	} + +	Party &party = _g407_party; +	party._magicalLightAmount = file->readSint16BE(); +	party._event73Count_ThievesEye = file->readByte(); +	party._event79Count_Footprints = file->readByte(); +	party._shieldDefense = file->readSint16BE(); +	party._fireShieldDefense = file->readSint16BE(); +	party._spellShieldDefense = file->readSint16BE(); +	party._scentCount = file->readByte(); +	party._freezeLifeTicks = file->readByte(); +	party._firstScentIndex = file->readByte(); +	party._lastScentIndex = file->readByte(); +	for (uint16 i = 0; i < 24; ++i) +		party._scents[i] = Scent(file->readUint16BE()); +	for (uint16 i = 0; i < 24; ++i) +		party._scentStrengths[i] = file->readByte(); +	party._event71Count_Invisibility = file->readByte(); +} + +ChampionIndex ChampionMan::f285_getIndexInCell(int16 cell) { +	for (uint16 i = 0; i < _g305_partyChampionCount; ++i) { +		if ((_gK71_champions[i]._cell == cell) && _gK71_champions[i]._currHealth) +			return (ChampionIndex)i; +	} + +	return kM1_ChampionNone; +} + +void ChampionMan::f278_resetDataToStartGame() { +	if (!_vm->_g298_newGame) { +		Thing L0787_T_Thing; +		if ((L0787_T_Thing = _g414_leaderHandObject) == Thing::_none) { +			_g415_leaderEmptyHanded = true; +			_g413_leaderHandObjectIconIndex = kM1_IconIndiceNone; +			_vm->_eventMan->f69_setMousePointer(); +		} else { +			f297_putObjectInLeaderHand(L0787_T_Thing, true); /* This call will add the weight of the leader hand object to the Load of the leader a first time */ +		} +		Champion *L0788_ps_Champion = _gK71_champions; +		int16 L0785_i_ChampionIndex; +		for (L0785_i_ChampionIndex = k0_ChampionFirst; L0785_i_ChampionIndex < _g305_partyChampionCount; L0785_i_ChampionIndex++, L0788_ps_Champion++) { +			clearFlag(L0788_ps_Champion->_attributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand); +			setFlag(L0788_ps_Champion->_attributes, k0x8000_ChampionAttributeActionHand | k0x1000_ChampionAttributeStatusBox | k0x0400_ChampionAttributeIcon); +		} +		f293_drawAllChampionStates(); +		if ((L0785_i_ChampionIndex = _g411_leaderIndex) != kM1_ChampionNone) { +			_g411_leaderIndex = kM1_ChampionNone; +			_vm->_eventMan->f368_commandSetLeader((ChampionIndex)L0785_i_ChampionIndex); +		} +		if ((L0785_i_ChampionIndex = _g514_magicCasterChampionIndex) != kM1_ChampionNone) { +			_g514_magicCasterChampionIndex = kM1_ChampionNone; +			_vm->_menuMan->f394_setMagicCasterAndDrawSpellArea(L0785_i_ChampionIndex); +		} +		return; +	} + +	_g414_leaderHandObject = Thing::_none; +	_g413_leaderHandObjectIconIndex = kM1_IconIndiceNone; +	_g415_leaderEmptyHanded = true; +} + +void ChampionMan::f280_addCandidateChampionToParty(uint16 championPortraitIndex) { +	if (!_g415_leaderEmptyHanded) +		return; + +	if (_g305_partyChampionCount == 4) +		return; + +	uint16 previousPartyChampionCount = _g305_partyChampionCount; +	Champion *championPtr = &_gK71_champions[previousPartyChampionCount]; +	championPtr->resetToZero(); +	// Strangerke - TODO: Check if the new code is possible to run on the older version (example: the portraits could be missing in the data) +	_vm->_displayMan->_g578_useByteBoxCoordinates = true; +	_vm->_displayMan->f132_blitToBitmap(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k26_ChampionPortraitsIndice), championPtr->_portrait, gBoxChampionPortrait, M27_getChampionPortraitX(championPortraitIndex), M28_getChampionPortraitY(championPortraitIndex), k128_byteWidth, k16_byteWidth, kM1_ColorNoTransparency); +	championPtr->_actionIndex = k255_ChampionActionNone; +	championPtr->_enableActionEventIndex = -1; +	championPtr->_hideDamageReceivedIndex = -1; +	championPtr->_dir = _vm->_dungeonMan->_g308_partyDir; +	uint16 viewCell = k0_ViewCellFronLeft; +	while (f285_getIndexInCell(M21_normalizeModulo4(viewCell + _vm->_dungeonMan->_g308_partyDir)) != kM1_ChampionNone) +		viewCell++; + +	championPtr->_cell = (ViewCell)M21_normalizeModulo4(viewCell + _vm->_dungeonMan->_g308_partyDir); +	championPtr->_attributes = k0x0400_ChampionAttributeIcon; +	championPtr->_directionMaximumDamageReceived = _vm->_dungeonMan->_g308_partyDir; +	championPtr->_food = 1500 + _vm->getRandomNumber(256); +	championPtr->_water = 1500 + _vm->getRandomNumber(256); +	for (int16 slotIdx = k0_ChampionSlotReadyHand; slotIdx < k30_ChampionSlotChest_1; slotIdx++) +		championPtr->_slots[slotIdx] = Thing::_none; + +	Thing curThing = _vm->_dungeonMan->f161_getSquareFirstThing(_vm->_dungeonMan->_g306_partyMapX, _vm->_dungeonMan->_g307_partyMapY); +	while (curThing.getType() != k2_TextstringType) +		curThing = _vm->_dungeonMan->f159_getNextThing(curThing); + +	char L0807_ac_DecodedChampionText[77]; +	char *decodedStringPtr = L0807_ac_DecodedChampionText; +	_vm->_dungeonMan->f168_decodeText(decodedStringPtr, curThing, (TextType)(k2_TextTypeScroll | k0x8000_DecodeEvenIfInvisible)); + +	uint16 charIdx = 0; +	char tmpChar; +	while ((tmpChar = *decodedStringPtr++) != '\n') +		championPtr->_name[charIdx++] = tmpChar; + +	championPtr->_name[charIdx] = '\0'; +	charIdx = 0; +	bool championTitleCopiedFl = false; +	for (;;) { /*_Infinite loop_*/ +		tmpChar = *decodedStringPtr++; +		if (tmpChar == '\n') { /* New line */ +			if (championTitleCopiedFl) +				break; +			championTitleCopiedFl = true; +		} else +			championPtr->_title[charIdx++] = tmpChar; +	} +	championPtr->_title[charIdx] = '\0'; +	if (*decodedStringPtr++ == 'M') +		setFlag(championPtr->_attributes, k0x0010_ChampionAttributeMale); + +	decodedStringPtr++; +	championPtr->_currHealth = championPtr->_maxHealth = f279_getDecodedValue(decodedStringPtr, 4); +	decodedStringPtr += 4; +	championPtr->_currStamina = championPtr->_maxStamina = f279_getDecodedValue(decodedStringPtr, 4); +	decodedStringPtr += 4; +	championPtr->_currMana = championPtr->_maxMana = f279_getDecodedValue(decodedStringPtr, 4); +	decodedStringPtr += 4; +	decodedStringPtr++; +	for (int16 statIdx = k0_ChampionStatLuck; statIdx <= k6_ChampionStatAntifire; statIdx++) { +		championPtr->_statistics[statIdx][k2_ChampionStatMinimum] = 30; +		championPtr->_statistics[statIdx][k1_ChampionStatCurrent] = championPtr->_statistics[statIdx][k0_ChampionStatMaximum] = f279_getDecodedValue(decodedStringPtr, 2); +		decodedStringPtr += 2; +	} +	championPtr->_statistics[k0_ChampionStatLuck][k2_ChampionStatMinimum] = 10; +	decodedStringPtr++; +	for (uint16 skillIdx = k4_ChampionSkillSwing; skillIdx <= k19_ChampionSkillWater; skillIdx++) { +		int skillValue = *decodedStringPtr++ - 'A'; +		if (skillValue > 0) +			championPtr->_skills[skillIdx]._experience = 125L << skillValue; +	} +	for (uint16 skillIdx = k0_ChampionSkillFighter; skillIdx <= k3_ChampionSkillWizard; skillIdx++) { +		int32 baseSkillExperience = 0; +		int16 hiddenSkillIndex = (skillIdx + 1) << 2; +		for (uint16 hiddenIdx = 0; hiddenIdx < 4; hiddenIdx++) +			baseSkillExperience += championPtr->_skills[hiddenSkillIndex + hiddenIdx]._experience; + +		championPtr->_skills[skillIdx]._experience = baseSkillExperience; +	} +	_g299_candidateChampionOrdinal = previousPartyChampionCount + 1; +	if (++_g305_partyChampionCount == 1) { +		_vm->_eventMan->f368_commandSetLeader(k0_ChampionFirst); +		_vm->_menuMan->_g508_refreshActionArea = true; +	} else { +		_vm->_menuMan->f388_clearActingChampion(); +		_vm->_menuMan->f386_drawActionIcon((ChampionIndex)(_g305_partyChampionCount - 1)); +	} + +	int16 curMapX = _vm->_dungeonMan->_g306_partyMapX; +	int16 curMapY = _vm->_dungeonMan->_g307_partyMapY; +	uint16 championObjectsCell = returnOppositeDir(_vm->_dungeonMan->_g308_partyDir); +	curMapX += _vm->_dirIntoStepCountEast[_vm->_dungeonMan->_g308_partyDir], curMapY += _vm->_dirIntoStepCountNorth[_vm->_dungeonMan->_g308_partyDir]; +	curThing = _vm->_dungeonMan->f161_getSquareFirstThing(curMapX, curMapY); +	int16 slotIdx = k13_ChampionSlotBackpackLine_1_1; +	while (curThing != Thing::_endOfList) { +		ThingType thingType = curThing.getType(); +		if ((thingType > k3_SensorThingType) && (curThing.getCell() == championObjectsCell)) { +			int16 objectAllowedSlots = g237_ObjectInfo[_vm->_dungeonMan->f141_getObjectInfoIndex(curThing)]._allowedSlots; +			uint16 curSlotIndex; +			switch (thingType) { +			case k6_ArmourThingType: { +				bool skipCheck = false; +				for (curSlotIndex = k2_ChampionSlotHead; curSlotIndex <= k5_ChampionSlotFeet; curSlotIndex++) { +					if (objectAllowedSlots & gSlotMasks[curSlotIndex]) { +						skipCheck = true; +						break; +					} +				} + +				if (skipCheck) +					break; + +				if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none)) +					curSlotIndex = k10_ChampionSlotNeck; +				else +					curSlotIndex = slotIdx++; + +				break; +			} +			case k5_WeaponThingType: +				if (championPtr->_slots[k1_ChampionSlotActionHand] == Thing::_none) +					curSlotIndex = k1_ChampionSlotActionHand; +				else if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none)) +					curSlotIndex = k10_ChampionSlotNeck; +				else +					curSlotIndex = slotIdx++; +				break; +			case k7_ScrollThingType: +			case k8_PotionThingType: +				if (championPtr->_slots[k11_ChampionSlotPouch_1] == Thing::_none) +					curSlotIndex = k11_ChampionSlotPouch_1; +				else if (championPtr->_slots[k6_ChampionSlotPouch_2] == Thing::_none) +					curSlotIndex = k6_ChampionSlotPouch_2; +				else if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none)) +					curSlotIndex = k10_ChampionSlotNeck; +				else +					curSlotIndex = slotIdx++; +				break; +			case k9_ContainerThingType: +			case k10_JunkThingType: +				if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none)) +					curSlotIndex = k10_ChampionSlotNeck; +				else +					curSlotIndex = slotIdx++; + +				break; +			default: +				break; +			} + +			while (championPtr->_slots[curSlotIndex] != Thing::_none) { +				if ((objectAllowedSlots & gSlotMasks[k10_ChampionSlotNeck]) && (championPtr->_slots[k10_ChampionSlotNeck] == Thing::_none)) +					curSlotIndex = k10_ChampionSlotNeck; +				else +					curSlotIndex = slotIdx++; +			} +			f301_addObjectInSlot((ChampionIndex)previousPartyChampionCount, curThing, (ChampionSlot)curSlotIndex); +		} +		curThing = _vm->_dungeonMan->f159_getNextThing(curThing); +	} +	_vm->_inventoryMan->f355_toggleInventory((ChampionIndex)previousPartyChampionCount); +	_vm->_menuMan->f456_drawDisabledMenu();; +} + +void ChampionMan::f287_drawChampionBarGraphs(ChampionIndex champIndex) { +	int16 barGraphHeights[3]; +	Champion *champ = &_gK71_champions[champIndex]; +	int16 barGraphIdx = 0; +	if (champ->_currHealth > 0) { +		int32 barGraphHeight = (((int32)champ->_currHealth << 10) * 25) / champ->_maxHealth; +		barGraphHeights[barGraphIdx++] = (barGraphHeight >> 10) + ((barGraphHeight & 0x000003FF) ? 1 : 0); +	} else +		barGraphHeights[barGraphIdx++] = 0; + +	if (champ->_currStamina > 0) { +		int32 barGraphHeight = (((int32)champ->_currStamina << 10) * 25) / champ->_maxStamina; +		barGraphHeights[barGraphIdx++] = (barGraphHeight >> 10) + ((barGraphHeight & 0x000003FF) ? 1 : 0); +	} else +		barGraphHeights[barGraphIdx++] = 0; + +	if (champ->_currMana > 0) { +		if (champ->_currMana > champ->_maxMana) +			barGraphHeights[barGraphIdx] = 25; +		else { +			int32 barGraphHeight = (((int32)champ->_currMana << 10) * 25) / champ->_maxMana; +			barGraphHeights[barGraphIdx] = (barGraphHeight >> 10) + ((barGraphHeight & 0x000003FF) ? 1 : 0); +		} +	} else { +		barGraphHeights[barGraphIdx] = 0; +	} +	_vm->_eventMan->f78_showMouse(); + +	// Strangerke - TO CHECK: if portraits, maybe the old (assembly) code is required for older versions +	Box box; +	box._x1 = champIndex * k69_ChampionStatusBoxSpacing + 46; +	box._x2 = box._x1 + 3; +	box._y1 = 2; +	box._y2 = 26; +	for (int16 barGraphIndex = 0; barGraphIndex < 3; barGraphIndex++) { +		int16 barGraphHeight = barGraphHeights[barGraphIndex]; +		if (barGraphHeight < 25) { +			box._y1 = 2; +			box._y2 = 27 - barGraphHeight; +			_vm->_displayMan->D24_fillScreenBox(box, k12_ColorDarkestGray); +		} +		if (barGraphHeight) { +			box._y1 = 27 - barGraphHeight; +			box._y2 = 26; +			_vm->_displayMan->D24_fillScreenBox(box, g46_ChampionColor[champIndex]); +		} +		box._x1 += 7; +		box._x2 += 7; +	} +	_vm->_eventMan->f77_hideMouse(); +} + + +uint16 ChampionMan::f306_getStaminaAdjustedValue(Champion *champ, int16 val) { +	int16 currStamina = champ->_currStamina; +	int16 halfMaxStamina = champ->_maxStamina / 2; +	if (currStamina < halfMaxStamina) { +		warning(false, "Possible undefined behavior in the original code"); +		val /= 2; +		return val + ((uint32)val * (uint32)currStamina) / halfMaxStamina; +	} +	return val; +} + +uint16 ChampionMan::f309_getMaximumLoad(Champion *champ) { +	uint16 maximumLoad = champ->getStatistic(k1_ChampionStatStrength, k1_ChampionStatCurrent) * 8 + 100; +	maximumLoad = f306_getStaminaAdjustedValue(champ, maximumLoad); +	int16 wounds = champ->getWounds(); +	if (wounds) +		maximumLoad -= maximumLoad >> (champ->getWoundsFlag(k0x0010_ChampionWoundLegs) ? 2 : 3); + +	if (_vm->_objectMan->f33_getIconIndex(champ->getSlot(k5_ChampionSlotFeet)) == k119_IconIndiceArmourElvenBoots) +		maximumLoad += maximumLoad * 16; + +	maximumLoad += 9; +	maximumLoad -= maximumLoad % 10; +	return maximumLoad; +} + +void ChampionMan::f292_drawChampionState(ChampionIndex champIndex) { +	int16 championStatusBoxX = champIndex * k69_ChampionStatusBoxSpacing; +	Champion *curChampion = &_gK71_champions[champIndex]; +	uint16 championAttributes = curChampion->_attributes; +	if (!getFlag(championAttributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand)) +		return; + +	bool isInventoryChampion = (_vm->M0_indexToOrdinal(champIndex) == _vm->_inventoryMan->_g432_inventoryChampionOrdinal); +	_vm->_displayMan->_g578_useByteBoxCoordinates = false; +	_vm->_eventMan->f78_showMouse(); +	if (getFlag(championAttributes, k0x1000_ChampionAttributeStatusBox)) { +		Box box; +		box._y1 = 0; +		box._y2 = 28; +		box._x1 = championStatusBoxX; +		box._x2 = box._x1 + 66; +		if (curChampion->_currHealth) { +			_vm->_displayMan->D24_fillScreenBox(box, k12_ColorDarkestGray); +			int16 nativeBitmapIndices[3]; +			for (uint16 i = 0; i < 3; ++i) +				nativeBitmapIndices[i] = 0; + +			uint16 borderCount = 0; +			if (_g407_party._fireShieldDefense > 0) +				nativeBitmapIndices[borderCount++] = k38_BorderPartyFireshieldIndice; + +			if (_g407_party._spellShieldDefense > 0) +				nativeBitmapIndices[borderCount++] = k39_BorderPartySpellshieldIndice; + +			if ((_g407_party._shieldDefense > 0) || curChampion->_shieldDefense) +				nativeBitmapIndices[borderCount++] = k37_BorderPartyShieldIndice; + +			while (borderCount--) +				_vm->_displayMan->f21_blitToScreen(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndices[borderCount]), &box, k40_byteWidth, k10_ColorFlesh, 29); + +			if (isInventoryChampion) { +				_vm->_inventoryMan->f354_drawStatusBoxPortrait(champIndex); +				setFlag(championAttributes, k0x0100_ChampionAttributeStatistics); +			} else +				setFlag(championAttributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x2000_ChampionAttributeWounds | k0x8000_ChampionAttributeActionHand); +		} else { +			_vm->_displayMan->f21_blitToScreen(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k8_StatusBoxDeadChampion), &box, k40_byteWidth, kM1_ColorNoTransparency, 29); +			_vm->_textMan->f53_printToLogicalScreen(championStatusBoxX + 1, 5, k13_ColorLightestGray, k1_ColorDarkGary, curChampion->_name); +			_vm->_menuMan->f386_drawActionIcon(champIndex); + +			clearFlag(curChampion->_attributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand); +			_vm->_eventMan->f77_hideMouse(); +			return; +		} +	} +	if (!(curChampion->_currHealth)) { +		clearFlag(curChampion->_attributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand); +		_vm->_eventMan->f77_hideMouse(); +		return; +	} + +	if (getFlag(championAttributes, k0x0080_ChampionAttributeNameTitle)) { +		Color nameColor = (champIndex == _g411_leaderIndex) ? k9_ColorGold : k13_ColorLightestGray; +		if (isInventoryChampion) { +			char *championName = curChampion->_name; +			_vm->_textMan->f52_printToViewport(3, 7, nameColor, championName); +			int16 championTitleX = 6 * strlen(championName) + 3; +			char titleFirstCharacter = curChampion->_title[0]; +			if ((titleFirstCharacter != ',') && (titleFirstCharacter != ';') && (titleFirstCharacter != '-')) +				championTitleX += 6; + +			_vm->_textMan->f52_printToViewport(championTitleX, 7, nameColor, curChampion->_title); +			setFlag(championAttributes, k0x4000_ChampionAttributeViewport); +		} else { +			Box box; +			box._y1 = 0; +			box._y2 = 6; +			box._x1 = championStatusBoxX; +			box._x2 = box._x1 + 42; +			_vm->_displayMan->D24_fillScreenBox(box, k1_ColorDarkGary); +			_vm->_textMan->f53_printToLogicalScreen(championStatusBoxX + 1, 5, nameColor, k1_ColorDarkGary, curChampion->_name); +		} +	} +	if (getFlag(championAttributes, k0x0100_ChampionAttributeStatistics)) { +		f287_drawChampionBarGraphs(champIndex); +		if (isInventoryChampion) { +			f290_drawHealthStaminaManaValues(curChampion); +			int16 nativeBitmapIndex; +			if ((curChampion->_food < 0) || (curChampion->_water < 0) || (curChampion->_poisonEventCount)) +				nativeBitmapIndex = k34_SlotBoxWoundedIndice; +			else +				nativeBitmapIndex = k33_SlotBoxNormalIndice; + +			_vm->_displayMan->f20_blitToViewport(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndex), gBoxMouth, k16_byteWidth, k12_ColorDarkestGray, 18); +			nativeBitmapIndex = k33_SlotBoxNormalIndice; +			for (int i = k1_ChampionStatStrength; i <= k6_ChampionStatAntifire; i++) { +				if ((curChampion->_statistics[i][k1_ChampionStatCurrent] < curChampion->_statistics[i][k0_ChampionStatMaximum])) { +					nativeBitmapIndex = k34_SlotBoxWoundedIndice; +					break; +				} +			} +			_vm->_displayMan->f20_blitToViewport(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndex), gBoxEye, k16_byteWidth, k12_ColorDarkestGray, 18); +			setFlag(championAttributes, k0x4000_ChampionAttributeViewport); +		} +	} +	if (getFlag(championAttributes, k0x2000_ChampionAttributeWounds)) { +		for (int i = isInventoryChampion ? k5_ChampionSlotFeet : k1_ChampionSlotActionHand; i >= k0_ChampionSlotReadyHand; i--) +			f291_drawSlot(champIndex, i); + +		if (isInventoryChampion) +			setFlag(championAttributes, k0x4000_ChampionAttributeViewport); +	} +	if (getFlag(championAttributes, k0x0200_ChampionAttributeLoad) && isInventoryChampion) { +		uint16 maxLoad = f309_getMaximumLoad(curChampion); +		Color loadColor; +		if (curChampion->_load > maxLoad) +			loadColor = k8_ColorRed; +		else if (((long)curChampion->_load << 3) > ((long)maxLoad * 5)) +			loadColor = k11_ColorYellow; +		else +			loadColor = k13_ColorLightestGray; + +		_vm->_textMan->f52_printToViewport(104, 132, loadColor, "LOAD "); +		maxLoad = curChampion->_load / 10; +		strcpy(_vm->_g353_stringBuildBuffer, f288_getStringFromInteger(maxLoad, true, 3).c_str()); +		strcat(_vm->_g353_stringBuildBuffer, "."); +		maxLoad = curChampion->_load - (maxLoad * 10); +		strcat(_vm->_g353_stringBuildBuffer, f288_getStringFromInteger(maxLoad, false, 1).c_str()); +		strcat(_vm->_g353_stringBuildBuffer, "/"); +		maxLoad = (f309_getMaximumLoad(curChampion) + 5) / 10; +		strcat(_vm->_g353_stringBuildBuffer, f288_getStringFromInteger(maxLoad, true, 3).c_str()); +		strcat(_vm->_g353_stringBuildBuffer, " KG"); +		_vm->_textMan->f52_printToViewport(148, 132, loadColor, _vm->_g353_stringBuildBuffer); +		setFlag(championAttributes, k0x4000_ChampionAttributeViewport); +	} +	uint16 championIconIndex = M26_championIconIndex(curChampion->_cell, _vm->_dungeonMan->_g308_partyDir); +	if (getFlag(championAttributes, k0x0400_ChampionAttributeIcon) && (_vm->_eventMan->_g599_useChampionIconOrdinalAsMousePointerBitmap != _vm->M0_indexToOrdinal(championIconIndex))) { +		_vm->_displayMan->D24_fillScreenBox(g54_BoxChampionIcons[championIconIndex], g46_ChampionColor[champIndex]); +		_vm->_displayMan->f132_blitToBitmap(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k28_ChampionIcons), _vm->_displayMan->_g348_bitmapScreen, g54_BoxChampionIcons[championIconIndex], M26_championIconIndex(curChampion->_dir, _vm->_dungeonMan->_g308_partyDir) * 19, 0, k40_byteWidth, k160_byteWidthScreen, k12_ColorDarkestGray, 14, k200_heightScreen); +	} +	if (getFlag(championAttributes, k0x0800_ChampionAttributePanel) && isInventoryChampion) { +		if (_vm->_g333_pressingMouth) +			_vm->_inventoryMan->f345_drawPanelFoodWaterPoisoned(); +		else if (_vm->_g331_pressingEye) { +			if (_g415_leaderEmptyHanded) +				_vm->_inventoryMan->f351_drawChampionSkillsAndStatistics(); +		} else +			_vm->_inventoryMan->f347_drawPanel(); + +		setFlag(championAttributes, k0x4000_ChampionAttributeViewport); +	} +	if (getFlag(championAttributes, k0x8000_ChampionAttributeActionHand)) { +		f291_drawSlot(champIndex, k1_ChampionSlotActionHand); +		_vm->_menuMan->f386_drawActionIcon(champIndex); +		if (isInventoryChampion) +			setFlag(championAttributes, k0x4000_ChampionAttributeViewport); +	} +	if (getFlag(championAttributes, k0x4000_ChampionAttributeViewport)) +		_vm->_displayMan->f97_drawViewport(k0_viewportNotDungeonView); + +	clearFlag(curChampion->_attributes, k0x0080_ChampionAttributeNameTitle | k0x0100_ChampionAttributeStatistics | k0x0200_ChampionAttributeLoad | k0x0400_ChampionAttributeIcon | k0x0800_ChampionAttributePanel | k0x1000_ChampionAttributeStatusBox | k0x2000_ChampionAttributeWounds | k0x4000_ChampionAttributeViewport | k0x8000_ChampionAttributeActionHand); +	_vm->_eventMan->f77_hideMouse(); +} + +uint16 ChampionMan::M26_championIconIndex(int16 val, Direction dir) { +	return ((val + 4 - dir) & 0x3); +} + +void ChampionMan::f290_drawHealthStaminaManaValues(Champion* champ) { +	f289_drawHealthOrStaminaOrManaValue(116, champ->_currHealth, champ->_maxHealth); +	f289_drawHealthOrStaminaOrManaValue(124, champ->_currStamina, champ->_maxStamina); +	f289_drawHealthOrStaminaOrManaValue(132, champ->_currMana, champ->_maxMana); +} + +void ChampionMan::f291_drawSlot(uint16 champIndex, int16 slotIndex) { +	int16 nativeBitmapIndex = -1; +	Champion *champ = &_gK71_champions[champIndex]; +	bool isInventoryChamp = (_vm->_inventoryMan->_g432_inventoryChampionOrdinal == _vm->M0_indexToOrdinal(champIndex)); + +	uint16 slotBoxIndex; +	if (!isInventoryChamp) { +		// If drawing a slot for a champion other than the champion whose inventory is open +		if ((slotIndex > k1_ChampionSlotActionHand) || (_g299_candidateChampionOrdinal == _vm->M0_indexToOrdinal(champIndex))) +			return; +		slotBoxIndex = (champIndex << 1) + slotIndex; +	} else +		slotBoxIndex = k8_SlotBoxInventoryFirstSlot + slotIndex; + +	Thing thing; +	if (slotIndex >= k30_ChampionSlotChest_1) +		thing = _vm->_inventoryMan->_g425_chestSlots[slotIndex - k30_ChampionSlotChest_1]; +	else +		thing = champ->getSlot((ChampionSlot)slotIndex); + +	SlotBox *slotBox = &_vm->_objectMan->_g30_slotBoxes[slotBoxIndex]; +	Box box; +	box._x1 = slotBox->_x - 1; +	box._y1 = slotBox->_y - 1; +	box._x2 = box._x1 + 17; +	box._y2 = box._y1 + 17; + +	if (!isInventoryChamp) +		_vm->_eventMan->f77_hideMouse(); + +	int16 iconIndex; +	if (thing == Thing::_none) { +		if (slotIndex <= k5_ChampionSlotFeet) { +			iconIndex = k212_IconIndiceReadyHand + (slotIndex << 1); +			if (champ->getWoundsFlag((ChampionWound)(1 << slotIndex))) { +				iconIndex++; +				nativeBitmapIndex = k34_SlotBoxWoundedIndice; +			} else +				nativeBitmapIndex = k33_SlotBoxNormalIndice; +		} else { +			if ((slotIndex >= k10_ChampionSlotNeck) && (slotIndex <= k13_ChampionSlotBackpackLine_1_1)) +				iconIndex = k208_IconIndiceNeck + (slotIndex - k10_ChampionSlotNeck); +			else +				iconIndex = k204_IconIndiceEmptyBox; +		} +	} else { +		iconIndex = _vm->_objectMan->f33_getIconIndex(thing); // BUG0_35 +		if (isInventoryChamp && (slotIndex == k1_ChampionSlotActionHand) && ((iconIndex == k144_IconIndiceContainerChestClosed) || (iconIndex == k30_IconIndiceScrollOpen))) { +			iconIndex++; +		} // BUG2_00 +		if (slotIndex <= k5_ChampionSlotFeet) { +			if (champ->getWoundsFlag((ChampionWound)(1 << slotIndex))) +				nativeBitmapIndex = k34_SlotBoxWoundedIndice; +			else +				nativeBitmapIndex = k33_SlotBoxNormalIndice; +		} +	} + +	if ((slotIndex == k1_ChampionSlotActionHand) && (_vm->M0_indexToOrdinal(champIndex) == _g506_actingChampionOrdinal)) +		nativeBitmapIndex = k35_SlotBoxActingHandIndice; + +	if (nativeBitmapIndex != -1) { +		_vm->_displayMan->_g578_useByteBoxCoordinates = false; +		if (isInventoryChamp) +			_vm->_displayMan->f132_blitToBitmap(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndex), +												_vm->_displayMan->_g296_bitmapViewport, box, 0, 0, 16, k112_byteWidthViewport, k12_ColorDarkestGray); +		else +			_vm->_displayMan->f132_blitToBitmap(_vm->_displayMan->f489_getNativeBitmapOrGraphic(nativeBitmapIndex), +												_vm->_displayMan->_g348_bitmapScreen, box, 0, 0, 16, k160_byteWidthScreen, k12_ColorDarkestGray); +	} + +	_vm->_objectMan->f38_drawIconInSlotBox(slotBoxIndex, iconIndex); + +	if (!isInventoryChamp) +		_vm->_eventMan->f78_showMouse(); +} + +void ChampionMan::f281_renameChampion(Champion* champ) { +#define k1_RENAME_CHAMPION_NAME 1 +#define k2_RENAME_CHAMPION_TITLE 2 +	static const char underscoreCharacterString[2] = "_"; +	static char renameChampionInputCharacterString[2] = " "; +	static const char reincarnateSpecialCharacters[6] = {',', '.', ';', ':', ' '}; + +	Box displayBox; +	displayBox._y1 = 3; +	displayBox._y2 = 8; +	displayBox._x1 = 3; +	displayBox._x2 = displayBox._x1 + 167; + +	_vm->_displayMan->f135_fillBoxBitmap(_vm->_displayMan->_g296_bitmapViewport, displayBox, k12_ColorDarkestGray, k112_byteWidthViewport, k136_heightViewport); +	_vm->_displayMan->f20_blitToViewport(_vm->_displayMan->f489_getNativeBitmapOrGraphic(k27_PanelRenameChampionIndice), g32_BoxPanel, k72_byteWidth, k4_ColorCyan, 73); +	_vm->_textMan->f52_printToViewport(177, 58, k13_ColorLightestGray, "_______"); +	_vm->_textMan->f52_printToViewport(105, 76, k13_ColorLightestGray, "___________________"); +	_vm->_eventMan->f78_showMouse(); +	_vm->_displayMan->f97_drawViewport(k0_viewportNotDungeonView); +	_vm->_eventMan->f67_setMousePointerToNormal(k0_pointerArrow); +	_vm->_eventMan->f77_hideMouse(); +	uint16 curCharacterIndex = 0; +	champ->_name[curCharacterIndex] = '\0'; +	champ->_title[0] = '\0'; +	int16 renamedChampionStringMode = k1_RENAME_CHAMPION_NAME; +	char *renamedChampionString = champ->_name; +	int16 textPosX = 177; +	int16 textPosY = 91; + +	for (;;) { /*_Infinite loop_*/ +		bool championTitleIsFull = ((renamedChampionStringMode == k2_RENAME_CHAMPION_TITLE) && (curCharacterIndex == 19)); +		if (!championTitleIsFull) { +			_vm->_eventMan->f78_showMouse(); +			_vm->_textMan->f40_printTextToBitmap(_vm->_displayMan->_g348_bitmapScreen, k160_byteWidthScreen, textPosX, textPosY, k9_ColorGold, k12_ColorDarkestGray, underscoreCharacterString, k200_heightScreen); +			_vm->_eventMan->f77_hideMouse(); +		} + +		int16 curCharacter = 256; +		while (curCharacter == 256) { +			Common::Event event; +			Common::EventType eventType = _vm->_eventMan->processInput(&event, &event); +			_vm->_displayMan->updateScreen(); +			if (_vm->_engineShouldQuit) +				return; +			_vm->_displayMan->updateScreen(); +				//_vm->f22_delay(1); + +			if (eventType == Common::EVENT_LBUTTONDOWN) { +				// If left mouse button status has changed + +				Common::Point mousePos = _vm->_eventMan->getMousePos(); +				if ((renamedChampionStringMode == k2_RENAME_CHAMPION_TITLE || (curCharacterIndex > 0)) && (mousePos.x >= 197) && (mousePos.x <= 215) && (mousePos.y >= 147) && (mousePos.y <= 155)) { /* Coordinates of 'OK' button */ +					int16 characterIndexBackup = curCharacterIndex; +					char L0821_ac_ChampionNameBackupString[8]; +					renamedChampionString = champ->_name; +					strcpy(L0821_ac_ChampionNameBackupString, renamedChampionString); +					curCharacterIndex = strlen(renamedChampionString); +					// Replace space characters on the right of the champion name by '\0' characters +					while (renamedChampionString[--curCharacterIndex] == ' ') +						renamedChampionString[curCharacterIndex] = '\0'; + +					bool found = false; +					for (uint16 idx = k0_ChampionFirst; idx < _g305_partyChampionCount - 1; idx++) { +						if (!strcmp(_gK71_champions[idx]._name, renamedChampionString)) { +							// If an existing champion already has the specified name for the new champion +							found = true; +							break; +						} +					} +					if (!found) +						return; + +					if (renamedChampionStringMode == k2_RENAME_CHAMPION_TITLE) +						renamedChampionString = champ->_title; + +					strcpy(renamedChampionString = champ->_name, L0821_ac_ChampionNameBackupString); +					curCharacterIndex = characterIndexBackup; +				} else { +					if ((mousePos.x >= 107) && (mousePos.x <= 175) && (mousePos.y >= 147) && (mousePos.y <= 155)) { /* Coordinates of 'BACKSPACE' button */ +						curCharacter = '\b'; +						break; +					} +#if 0 +					if ((mousePos.x < 107) || (mousePos.x > 215) || (mousePos.y < 116) || (mousePos.y > 144)) {/* Coordinates of table of all other characters */ +						//goto T0281023; +					} +					if (!((mousePos.x + 4) % 10) || (!((mousePos.y + 5) % 10) && ((mousePos.x < 207) || (mousePos.y != 135)))) { +						//goto T0281023; +					} +#endif +					curCharacter = 'A' + (11 * ((mousePos.y - 116) / 10)) + ((mousePos.x - 107) / 10); +					if ((curCharacter == 86) || (curCharacter == 97)) { +						// The 'Return' button occupies two cells in the table +						curCharacter = '\r'; /* Carriage return */ +						break; +					} + +					if (curCharacter >= 87) +						// Compensate for the first cell occupied by 'Return' button +						curCharacter--; + +					if (curCharacter > 'Z') +						curCharacter = reincarnateSpecialCharacters[(curCharacter - 'Z') - 1]; + +					break; +				} +			} else if (eventType == Common::EVENT_KEYDOWN) +				curCharacter = event.kbd.ascii; +		} + +		if ((curCharacter >= 'a') && (curCharacter <= 'z')) +			curCharacter -= 32; // Convert to uppercase + +		if (((curCharacter >= 'A') && (curCharacter <= 'Z')) || (curCharacter == '.') || (curCharacter == ',') || (curCharacter == ';') || (curCharacter == ':') || (curCharacter == ' ')) { +			if ((curCharacter != ' ') || curCharacterIndex != 0) { +				if (!championTitleIsFull) { +					renameChampionInputCharacterString[0] = curCharacter; +					_vm->_eventMan->f78_showMouse(); +					_vm->_textMan->f40_printTextToBitmap(_vm->_displayMan->_g348_bitmapScreen, k160_byteWidthScreen, textPosX, textPosY, k13_ColorLightestGray, k12_ColorDarkestGray, renameChampionInputCharacterString, k200_heightScreen); +					_vm->_eventMan->f77_hideMouse(); +					renamedChampionString[curCharacterIndex++] = curCharacter; +					renamedChampionString[curCharacterIndex] = '\0'; +					textPosX += 6; +					if ((renamedChampionStringMode == k1_RENAME_CHAMPION_NAME) && (curCharacterIndex == 7)) { +						renamedChampionStringMode = k2_RENAME_CHAMPION_TITLE; +						renamedChampionString = champ->_title; +						textPosX = 105; +						textPosY = 109; +						curCharacterIndex = 0; +					} +				} +			} +		} else if (curCharacter == '\r') { // Carriage return +			if ((renamedChampionStringMode == k1_RENAME_CHAMPION_NAME) && (curCharacterIndex > 0)) { +				_vm->_eventMan->f78_showMouse(); +				_vm->_textMan->f40_printTextToBitmap(_vm->_displayMan->_g348_bitmapScreen, k160_byteWidthScreen, textPosX, textPosY, k13_ColorLightestGray, k12_ColorDarkestGray, underscoreCharacterString, k200_heightScreen); +				_vm->_eventMan->f77_hideMouse(); +				renamedChampionStringMode = k2_RENAME_CHAMPION_TITLE; +				renamedChampionString = champ->_title; +				textPosX = 105; +				textPosY = 109; +				curCharacterIndex = 0; +			} +		} else if (curCharacter == '\b') { // Backspace +			if ((renamedChampionStringMode == k1_RENAME_CHAMPION_NAME) && (curCharacterIndex == 0)) +				continue; + +			if (!championTitleIsFull) { +				_vm->_eventMan->f78_showMouse(); +				_vm->_textMan->f40_printTextToBitmap(_vm->_displayMan->_g348_bitmapScreen, k160_byteWidthScreen, textPosX, textPosY, k13_ColorLightestGray, k12_ColorDarkestGray, underscoreCharacterString, k200_heightScreen); +				_vm->_eventMan->f77_hideMouse(); +			} +			if (curCharacterIndex == 0) { +				renamedChampionString = champ->_name; +				curCharacterIndex = strlen(renamedChampionString) - 1; +				renamedChampionStringMode = k1_RENAME_CHAMPION_NAME; +				textPosX = 177 + (curCharacterIndex * 6); +				textPosY = 91; +			} else { +				curCharacterIndex--; +				textPosX -= 6; +			} +			renamedChampionString[curCharacterIndex] = '\0'; +		} +	} +} + +uint16 ChampionMan::f303_getSkillLevel(int16 champIndex, uint16 skillIndex) { +	if (_g300_partyIsSleeping) +		return 1; + +	bool ignoreTmpExp = getFlag(skillIndex, k0x8000_IgnoreTemporaryExperience); +	bool ignoreObjModifiers = getFlag(skillIndex, k0x4000_IgnoreObjectModifiers); +	clearFlag(skillIndex, k0x8000_IgnoreTemporaryExperience | k0x4000_IgnoreObjectModifiers); +	Champion *champ = &_gK71_champions[champIndex]; +	Skill *skill = &champ->_skills[skillIndex]; +	int32 exp = skill->_experience; +	if (!ignoreTmpExp) +		exp += skill->_temporaryExperience; + +	if (skillIndex > k3_ChampionSkillWizard) { +		// Hidden skill +		skill = &champ->_skills[(skillIndex - k4_ChampionSkillSwing) >> 2]; +		exp += skill->_experience; // Add experience in the base skill +		if (!ignoreTmpExp) +			exp += skill->_temporaryExperience; + +		exp >>= 1; // Halve experience to get average of base skill + hidden skill experience +	} +	int16 skillLevel = 1; +	while (exp >= 500) { +		exp >>= 1; +		skillLevel++; +	} +	if (!ignoreObjModifiers) { +		int16 actionHandIconIndex = _vm->_objectMan->f33_getIconIndex(champ->_slots[k1_ChampionSlotActionHand]); +		if (actionHandIconIndex == k27_IconIndiceWeaponTheFirestaff) +			skillLevel++; +		else if (actionHandIconIndex == k28_IconIndiceWeaponTheFirestaffComplete) +			skillLevel += 2; + +		int16 neckIconIndex = _vm->_objectMan->f33_getIconIndex(champ->_slots[k10_ChampionSlotNeck]); +		switch (skillIndex) { +		case k3_ChampionSkillWizard: +			if (neckIconIndex == k124_IconIndiceJunkPendantFeral) +				skillLevel += 1; +			break; +		case k13_ChampionSkillHeal: +			// The skill modifiers of these two objects are not cumulative +			if ((neckIconIndex == k120_IconIndiceJunkGemOfAges) || (actionHandIconIndex == k66_IconIndiceWeaponSceptreOfLyf)) +				skillLevel += 1; +			break; +		case k14_ChampionSkillInfluence: +			if (neckIconIndex == k122_IconIndiceJunkMoonstone) +				skillLevel += 1; +			break; +		case k15_ChampionSkillDefend: +			if (neckIconIndex == k121_IconIndiceJunkEkkhardCross) +				skillLevel += 1; +			break; +		default: +			break; +		} +	} +	return skillLevel; +} + +} diff --git a/engines/dm/champion.h b/engines/dm/champion.h index 04ab76988f..a94bdcca8a 100644 --- a/engines/dm/champion.h +++ b/engines/dm/champion.h @@ -513,6 +513,7 @@ class ChampionMan {  	int16 _g410_championPendingWounds[4]; // @ G0410_ai_ChampionPendingWounds  	int16 _g409_championPendingDamage[4]; // @ G0409_ai_ChampionPendingDamage  public: +  	Champion _gK71_champions[4]; // @ K0071_as_Champions  	uint16 _g305_partyChampionCount;	// @ G0305_ui_PartyChampionCount  	bool _g303_partyDead; // @ G0303_B_PartyDead diff --git a/engines/dm/console.cpp b/engines/dm/console.cpp index e2618507f9..a1600661bc 100644 --- a/engines/dm/console.cpp +++ b/engines/dm/console.cpp @@ -30,6 +30,44 @@  namespace DM { -Console::Console(DM::DMEngine* vm) : _vm(vm) {} +Console::Console(DM::DMEngine* vm) : _vm(vm) { +	_debugGodmodeMana = false; +	_debugGodmodeHP = false; +	_debugGodmodeStamina = false; -}
\ No newline at end of file +	registerCmd("godmode", WRAP_METHOD(Console, Cmd_godmode)); +} + +bool Console::Cmd_godmode(int argc, const char** argv) { +	if (argc < 3) +		goto argumentError; + +	bool setFlagTo; + +	if (strcmp("on", argv[2]) == 0) { +		setFlagTo = true; +	} else if (strcmp("off", argv[2]) == 0) { +		setFlagTo = false; +	} else +		goto argumentError; + +	if (strcmp("all", argv[1]) == 0) { +		_debugGodmodeHP = _debugGodmodeMana = _debugGodmodeStamina = setFlagTo; +	} else if (strcmp("mana", argv[1]) == 0) { +		_debugGodmodeMana = setFlagTo; +	} else if (strcmp("hp", argv[1]) == 0) { +		_debugGodmodeHP = setFlagTo; +	} else if (strcmp("stamina", argv[1]) == 0) { +		_debugGodmodeStamina = setFlagTo; +	} else +		goto argumentError; + +	debugPrintf("God mode set for %s to %s\n", argv[1], argv[2]); +	return true; + +argumentError: +	debugPrintf("Usage: %s <all/mana/hp/stamina> <on/off>\n", argv[0]); +	return true; +} + +} diff --git a/engines/dm/console.h b/engines/dm/console.h index eab2a32e68..0bfcfcef64 100644 --- a/engines/dm/console.h +++ b/engines/dm/console.h @@ -36,7 +36,12 @@ class DMEngine;  class Console : public GUI::Debugger {  	DMEngine *_vm;  public: +	bool _debugGodmodeMana; +	bool _debugGodmodeHP; +	bool _debugGodmodeStamina; +  	explicit Console(DM::DMEngine *vm);  	virtual ~Console(void) {} +	bool Cmd_godmode(int argc, const char **argv);  };  } diff --git a/engines/dm/dm.cpp b/engines/dm/dm.cpp index 2f52b07ff6..8cd5771302 100644 --- a/engines/dm/dm.cpp +++ b/engines/dm/dm.cpp @@ -367,8 +367,21 @@ void DMEngine::f2_gameloop() {  	while (true) {  		if (_engineShouldQuit)  			return; +		 +		// DEBUG CODE +		for (int16 i = 0; i < _championMan->_g305_partyChampionCount; ++i) { +			Champion &champ = _championMan->_gK71_champions[i]; +			if (_console->_debugGodmodeHP) +				champ._currHealth = champ._maxHealth; +			if (_console->_debugGodmodeMana) +				champ._currMana = champ._maxMana; +			if (_console->_debugGodmodeStamina) +				champ._currStamina = champ._maxStamina; +		}  		for (;;) { +			 +  			if (_g327_newPartyMapIndex != kM1_mapIndexNone) {  				f3_processNewPartyMap(_g327_newPartyMapIndex);  				_moveSens->f267_getMoveResult(Thing::_party, kM1_MapXNotOnASquare, 0, _dungeonMan->_g306_partyMapX, _dungeonMan->_g307_partyMapY); | 
