2016-08-26 22:51:17 +02:00
/* 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/)
*/
2016-09-03 10:38:43 +02:00
# include "dm/champion.h"
# include "dm/dungeonman.h"
# include "dm/eventman.h"
# include "dm/menus.h"
# include "dm/inventory.h"
# include "dm/objectman.h"
# include "dm/text.h"
# include "dm/timeline.h"
# include "dm/projexpl.h"
# include "dm/group.h"
# include "dm/movesens.h"
# include "dm/sounds.h"
2016-08-26 22:51:17 +02:00
namespace DM {
2016-08-23 07:54:16 +02:00
void Champion : : resetToZero ( ) {
for ( int16 i = 0 ; i < 30 ; + + i )
2017-01-31 18:15:31 +01:00
_slots [ i ] = _vm - > _thingNone ;
2016-08-23 07:54:16 +02:00
for ( int16 i = 0 ; i < 20 ; + + i )
_skills [ i ] . resetToZero ( ) ;
_attributes = _wounds = 0 ;
memset ( _statistics , 0 , 7 * 3 ) ;
memset ( _name , ' \0 ' , 8 ) ;
memset ( _title , ' \0 ' , 20 ) ;
2016-09-11 00:33:54 +02:00
_dir = kDMDirNorth ;
2016-09-16 07:46:10 +02:00
_cell = kDMViewCellFronLeft ;
2016-09-10 14:31:49 +02:00
_actionIndex = kDMActionN ;
2016-08-23 07:54:16 +02:00
_symbolStep = 0 ;
memset ( _symbols , ' \0 ' , 5 ) ;
_directionMaximumDamageReceived = _maximumDamageReceived = _poisonEventCount = _enableActionEventIndex = 0 ;
_hideDamageReceivedIndex = _currHealth = _maxHealth = _currStamina = _maxStamina = _currMana = _maxMana = 0 ;
_actionDefense = _food = _water = _load = _shieldDefense = 0 ;
memset ( _portrait , 0 , 464 ) ;
}
void Champion : : setWoundsFlag ( ChampionWound flag , bool value ) {
if ( value )
_wounds | = flag ;
else
_wounds & = ~ flag ;
}
void Champion : : setAttributeFlag ( ChampionAttribute flag , bool value ) {
if ( value )
_attributes | = flag ;
else
_attributes & = ~ flag ;
}
2016-08-15 20:25:40 +02:00
void ChampionMan : : initConstants ( ) {
2016-09-22 07:02:49 +02:00
static const char * baseSkillNameEN [ 4 ] = { " FIGHTER " , " NINJA " , " PRIEST " , " WIZARD " } ;
static const char * baseSkillNameDE [ 4 ] = { " KAEMPFER " , " NINJA " , " PRIESTER " , " MAGIER " } ;
static const char * baseSkillNameFR [ 4 ] = { " GUERRIER " , " NINJA " , " PRETRE " , " SORCIER " } ;
2016-08-18 21:18:08 +02:00
static Box boxChampionIcons [ 4 ] = {
Box ( 281 , 299 , 0 , 13 ) ,
Box ( 301 , 319 , 0 , 13 ) ,
Box ( 301 , 319 , 15 , 28 ) ,
Box ( 281 , 299 , 15 , 28 )
} ;
2016-08-15 20:25:40 +02:00
2016-09-16 07:46:10 +02:00
static Color championColor [ 4 ] = { kDMColorLightGreen , kDMColorYellow , kDMColorRed , kDMColorBlue } ;
2016-08-20 14:22:47 +02:00
int16 lightPowerToLightAmount [ 16 ] = { 0 , 5 , 12 , 24 , 33 , 40 , 46 , 51 , 59 , 68 , 76 , 82 , 89 , 94 , 97 , 100 } ;
2016-08-21 14:25:06 +02:00
uint16 slotMasks [ 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 */
} ;
2016-09-10 21:50:57 +02:00
_boxChampionPortrait = Box ( 0 , 31 , 0 , 28 ) ; // @ G0047_s_Graphic562_Box_ChampionPortrait
2016-08-18 21:18:08 +02:00
2016-08-26 07:23:56 +02:00
const char * * baseSkillName ;
2016-08-18 21:18:08 +02:00
switch ( _vm - > getGameLanguage ( ) ) { // localized
2016-09-10 21:50:57 +02:00
case Common : : EN_ANY :
2016-09-22 07:02:49 +02:00
baseSkillName = baseSkillNameEN ;
2016-08-18 21:18:08 +02:00
break ;
case Common : : DE_DEU :
2016-09-22 07:02:49 +02:00
baseSkillName = baseSkillNameDE ;
2016-08-18 21:18:08 +02:00
break ;
case Common : : FR_FRA :
2016-09-22 07:02:49 +02:00
baseSkillName = baseSkillNameFR ;
2016-08-18 21:18:08 +02:00
break ;
default :
error ( " Unexpected language used " ) ;
}
for ( int i = 0 ; i < 4 ; + + i ) {
2016-08-26 07:23:56 +02:00
_baseSkillName [ i ] = baseSkillName [ i ] ;
2016-08-18 21:18:08 +02:00
_championColor [ i ] = championColor [ i ] ;
_boxChampionIcons [ i ] = boxChampionIcons [ i ] ;
2016-08-15 20:25:40 +02:00
}
2016-08-20 14:22:47 +02:00
for ( int i = 0 ; i < 16 ; i + + )
_lightPowerToLightAmount [ i ] = lightPowerToLightAmount [ i ] ;
2016-08-21 14:25:06 +02:00
for ( int i = 0 ; i < 38 ; i + + )
_slotMasks [ i ] = slotMasks [ i ] ;
2016-08-15 20:25:40 +02:00
}
2016-08-26 22:51:17 +02:00
ChampionMan : : ChampionMan ( DMEngine * vm ) : _vm ( vm ) {
2017-01-31 18:15:31 +01:00
_champions = new Champion [ 4 ] ;
2016-08-26 22:51:17 +02:00
for ( uint16 i = 0 ; i < 4 ; + + i ) {
2017-01-31 18:15:31 +01:00
_champions [ i ] . setVm ( _vm ) ;
2016-08-23 07:54:16 +02:00
_championPendingDamage [ i ] = 0 ;
_championPendingWounds [ i ] = 0 ;
_champions [ i ] . resetToZero ( ) ;
}
_partyChampionCount = 0 ;
_partyDead = false ;
_leaderHandObject = Thing ( 0 ) ;
2016-09-09 07:12:36 +02:00
_leaderIndex = kDMChampionNone ;
2016-08-23 07:54:16 +02:00
_candidateChampionOrdinal = 0 ;
_partyIsSleeping = false ;
_actingChampionOrdinal = 0 ;
_leaderHandObjectIconIndex = ( IconIndice ) 0 ;
_leaderEmptyHanded = false ;
_party . resetToZero ( ) ;
2016-09-09 07:12:36 +02:00
_magicCasterChampionIndex = kDMChampionNone ;
2016-08-23 07:54:16 +02:00
_mousePointerHiddenToDrawChangedObjIconOnScreen = false ;
2016-08-16 09:15:53 +02:00
initConstants ( ) ;
2016-08-26 22:51:17 +02:00
}
2017-01-31 18:15:31 +01:00
ChampionMan : : ~ ChampionMan ( ) {
delete [ ] _champions ;
}
2016-08-23 07:54:16 +02:00
bool ChampionMan : : isLeaderHandObjectThrown ( int16 side ) {
2016-09-09 07:12:36 +02:00
if ( _leaderIndex = = kDMChampionNone )
2016-08-26 22:51:17 +02:00
return false ;
2016-08-18 21:18:08 +02:00
2016-09-10 11:47:36 +02:00
return isObjectThrown ( _leaderIndex , kDMSlotLeaderHand , side ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
bool ChampionMan : : isObjectThrown ( uint16 champIndex , int16 slotIndex , int16 side ) {
2016-08-26 22:51:17 +02:00
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 */
2016-08-23 07:54:16 +02:00
if ( _leaderEmptyHanded )
2016-08-26 22:51:17 +02:00
return false ;
2016-08-23 07:54:16 +02:00
curThing = getObjectRemovedFromLeaderHand ( ) ;
curChampion = & _champions [ champIndex ] ;
2016-09-10 11:47:36 +02:00
actionHandThing = curChampion - > getSlot ( kDMSlotActionHand ) ;
curChampion - > setSlot ( kDMSlotActionHand , curThing ) ;
slotIndex = kDMSlotActionHand ;
2016-08-26 22:51:17 +02:00
throwingLeaderHandObjectFl = true ;
}
2016-08-23 07:54:16 +02:00
int16 kineticEnergy = getStrength ( champIndex , slotIndex ) ;
2016-08-26 22:51:17 +02:00
if ( throwingLeaderHandObjectFl ) {
// In this case, curChampion and actionHandThing are set.
curChampion - > setSlot ( ( ChampionSlot ) slotIndex , actionHandThing ) ;
} else {
2016-08-23 07:54:16 +02:00
curThing = getObjectRemovedFromSlot ( champIndex , slotIndex ) ;
2017-01-31 18:15:31 +01:00
if ( curThing = = _vm - > _thingNone )
2016-08-26 22:51:17 +02:00
return false ;
}
2016-09-22 07:02:49 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
_vm - > _sound - > requestPlay ( kDMSoundIndexAttackSkelettonAnimatedArmorDethKnight , dungeon . _partyMapX , dungeon . _partyMapY , kDMSoundModePlayIfPrioritized ) ;
2016-08-23 07:54:16 +02:00
decrementStamina ( champIndex , getThrowingStaminaCost ( curThing ) ) ;
disableAction ( champIndex , 4 ) ;
2016-08-26 22:51:17 +02:00
int16 experience = 8 ;
int16 weaponKineticEnergy = 1 ;
2016-09-11 00:33:54 +02:00
if ( curThing . getType ( ) = = kDMThingTypeWeapon ) {
2016-08-26 22:51:17 +02:00
experience + = 4 ;
2016-09-22 07:02:49 +02:00
WeaponInfo * curWeapon = dungeon . getWeaponInfo ( curThing ) ;
2016-09-11 23:06:29 +02:00
if ( curWeapon - > _class < = kDMWeaponClassPoisinDart ) {
2016-08-26 22:51:17 +02:00
weaponKineticEnergy = curWeapon - > _kineticEnergy ;
experience + = weaponKineticEnergy > > 2 ;
}
}
2016-09-09 07:32:32 +02:00
addSkillExperience ( champIndex , kDMSkillThrow , experience ) ;
2016-08-26 22:51:17 +02:00
kineticEnergy + = weaponKineticEnergy ;
2016-09-09 07:32:32 +02:00
int16 skillLevel = getSkillLevel ( ( ChampionIndex ) champIndex , kDMSkillThrow ) ;
2016-08-26 22:51:17 +02:00
kineticEnergy + = _vm - > getRandomNumber ( 16 ) + ( kineticEnergy > > 1 ) + skillLevel ;
2016-09-11 11:10:22 +02:00
int16 attack = CLIP < int16 > ( 40 , ( ( skillLevel < < 3 ) + _vm - > getRandomNumber ( 32 ) ) , 200 ) ;
2016-08-26 22:51:17 +02:00
int16 stepEnergy = MAX ( 5 , 11 - skillLevel ) ;
2016-09-22 07:02:49 +02:00
_vm - > _projexpl - > createProjectile ( curThing , dungeon . _partyMapX , dungeon . _partyMapY ,
_vm - > normalizeModulo4 ( dungeon . _partyDir + side ) ,
dungeon . _partyDir , kineticEnergy , attack , stepEnergy ) ;
2016-08-23 23:36:18 +02:00
_vm - > _projectileDisableMovementTicks = 4 ;
2016-09-22 07:02:49 +02:00
_vm - > _lastProjectileDisabledMovementDirection = dungeon . _partyDir ;
2016-08-23 07:54:16 +02:00
drawChampionState ( ( ChampionIndex ) champIndex ) ;
2016-08-26 22:51:17 +02:00
return true ;
}
2016-08-23 07:54:16 +02:00
uint16 ChampionMan : : getChampionPortraitX ( uint16 index ) {
2016-08-26 22:51:17 +02:00
return ( ( index ) & 0x7 ) < < 5 ;
}
2016-08-23 07:54:16 +02:00
uint16 ChampionMan : : getChampionPortraitY ( uint16 index ) {
2016-08-26 22:51:17 +02:00
return ( ( index ) > > 3 ) * 29 ;
}
2016-08-23 07:54:16 +02:00
int16 ChampionMan : : getDecodedValue ( char * string , uint16 characterCount ) {
2016-08-26 22:51:17 +02:00
int val = 0 ;
for ( uint16 i = 0 ; i < characterCount ; + + i ) {
val = ( val < < 4 ) + ( string [ i ] - ' A ' ) ;
}
return val ;
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : drawHealthOrStaminaOrManaValue ( int16 posY , int16 currVal , int16 maxVal ) {
2016-09-25 07:42:35 +02:00
TextMan & txtMan = * _vm - > _textMan ;
2016-08-23 07:54:16 +02:00
Common : : String tmp = getStringFromInteger ( currVal , true , 3 ) ;
2016-09-25 07:42:35 +02:00
txtMan . printToViewport ( 55 , posY , kDMColorLightestGray , tmp . c_str ( ) ) ;
txtMan . printToViewport ( 73 , posY , kDMColorLightestGray , " / " ) ;
2016-08-23 07:54:16 +02:00
tmp = getStringFromInteger ( maxVal , true , 3 ) ;
2016-09-25 07:42:35 +02:00
txtMan . printToViewport ( 79 , posY , kDMColorLightestGray , tmp . c_str ( ) ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
uint16 ChampionMan : : getHandSlotIndex ( uint16 slotBoxIndex ) {
2016-08-26 22:51:17 +02:00
return slotBoxIndex & 0x1 ;
}
2016-08-15 20:25:40 +02:00
2016-08-23 07:54:16 +02:00
Common : : String ChampionMan : : getStringFromInteger ( uint16 val , bool padding , uint16 paddingCharCount ) {
2016-08-26 22:51:17 +02:00
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 ;
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : applyModifiersToStatistics ( Champion * champ , int16 slotIndex , int16 iconIndex , int16 modifierFactor , Thing thing ) {
2016-09-09 07:32:32 +02:00
int16 statIndex = kDMStatLuck ;
2016-08-26 22:51:17 +02:00
int16 modifier = 0 ;
ThingType thingType = thing . getType ( ) ;
bool cursed = false ;
2016-09-11 00:33:54 +02:00
if ( ( ( thingType = = kDMThingTypeWeapon ) | | ( thingType = = kDMThingTypeArmour ) )
2016-09-10 11:47:36 +02:00
& & ( slotIndex > = kDMSlotReadyHand ) & & ( slotIndex < = kDMSlotQuiverLine1_1 ) ) {
2016-09-11 00:33:54 +02:00
if ( thingType = = kDMThingTypeWeapon ) {
2016-08-24 08:03:55 +02:00
Weapon * weapon = ( Weapon * ) _vm - > _dungeonMan - > getThingData ( thing ) ;
2016-08-26 22:51:17 +02:00
cursed = weapon - > getCursed ( ) ;
} else {
// k6_ArmourThingType
2016-08-24 08:03:55 +02:00
Armour * armour = ( Armour * ) _vm - > _dungeonMan - > getThingData ( thing ) ;
2016-08-26 22:51:17 +02:00
cursed = armour - > getCursed ( ) ;
}
if ( cursed ) {
2016-09-09 07:32:32 +02:00
statIndex = kDMStatLuck ;
2016-08-26 22:51:17 +02:00
modifier = - 3 ;
}
}
if ( ! cursed ) {
2016-09-09 07:32:32 +02:00
statIndex = ( ChampionStatType ) thingType ; // variable sharing
2016-08-26 22:51:17 +02:00
2016-09-10 11:47:36 +02:00
if ( ( iconIndex = = kDMIconIndiceJunkRabbitsFoot ) & & ( slotIndex < kDMSlotChest1 ) ) {
2016-09-09 07:32:32 +02:00
statIndex = kDMStatLuck ;
2016-08-26 22:51:17 +02:00
modifier = 10 ;
2016-09-10 11:47:36 +02:00
} else if ( slotIndex = = kDMSlotActionHand ) {
2016-09-09 07:12:36 +02:00
if ( iconIndex = = kDMIconIndiceWeaponMaceOfOrder ) {
2016-09-09 07:32:32 +02:00
statIndex = kDMStatStrength ;
2016-08-26 22:51:17 +02:00
modifier = 5 ;
} else {
2016-09-09 07:32:32 +02:00
statIndex = kDMStatMana ;
2016-09-09 07:12:36 +02:00
if ( ( iconIndex > = kDMIconIndiceWeaponStaffOfClawsEmpty ) & & ( iconIndex < = kDMIconIndiceWeaponStaffOfClawsFull ) ) {
2016-08-26 22:51:17 +02:00
modifier = 4 ;
} else {
switch ( iconIndex ) {
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponDeltaSideSplitter :
2016-08-26 22:51:17 +02:00
modifier = 1 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponTheInquisitorDragonFang :
2016-08-26 22:51:17 +02:00
modifier = 2 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponVorpalBlade :
2016-08-26 22:51:17 +02:00
modifier = 4 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponStaff :
2016-08-26 22:51:17 +02:00
modifier = 2 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponWand :
2016-08-26 22:51:17 +02:00
modifier = 1 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponTeowand :
2016-08-26 22:51:17 +02:00
modifier = 6 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponYewStaff :
2016-08-26 22:51:17 +02:00
modifier = 4 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponStaffOfManarStaffOfIrra :
2016-08-26 22:51:17 +02:00
modifier = 10 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponSnakeStaffCrossOfNeta :
2016-08-26 22:51:17 +02:00
modifier = 8 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponTheConduitSerpentStaff :
2016-08-26 22:51:17 +02:00
modifier = 16 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponDragonSpit :
2016-08-26 22:51:17 +02:00
modifier = 7 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceWeaponSceptreOfLyf :
2016-08-26 22:51:17 +02:00
modifier = 5 ;
break ;
default :
break ;
}
}
}
2016-09-10 11:47:36 +02:00
} else if ( slotIndex = = kDMSlotLegs ) {
2016-09-09 07:12:36 +02:00
if ( iconIndex = = kDMIconIndiceArmourPowertowers ) {
2016-09-09 07:32:32 +02:00
statIndex = kDMStatStrength ;
2016-08-26 22:51:17 +02:00
modifier = 10 ;
}
2016-09-10 11:47:36 +02:00
} else if ( slotIndex = = kDMSlotHead ) {
2016-08-26 22:51:17 +02:00
switch ( iconIndex ) {
2016-09-09 07:12:36 +02:00
case kDMIconIndiceArmourCrownOfNerra :
2016-09-09 07:32:32 +02:00
statIndex = kDMStatWisdom ;
2016-08-26 22:51:17 +02:00
modifier = 10 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceArmourDexhelm :
2016-09-09 07:32:32 +02:00
statIndex = kDMStatDexterity ;
2016-08-26 22:51:17 +02:00
modifier = 10 ;
break ;
default :
break ;
}
2016-09-10 11:47:36 +02:00
} else if ( slotIndex = = kDMSlotTorso ) {
2016-08-26 22:51:17 +02:00
switch ( iconIndex ) {
2016-09-09 07:12:36 +02:00
case kDMIconIndiceArmourFlamebain :
2016-09-09 07:32:32 +02:00
statIndex = kDMStatAntifire ;
2016-08-26 22:51:17 +02:00
modifier = 12 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceArmourCloakOfNight :
2016-09-09 07:32:32 +02:00
statIndex = kDMStatDexterity ;
2016-08-26 22:51:17 +02:00
modifier = 8 ;
break ;
default :
break ;
}
2016-09-10 11:47:36 +02:00
} else if ( slotIndex = = kDMSlotNeck ) {
2016-08-26 22:51:17 +02:00
switch ( iconIndex ) {
2016-09-09 07:12:36 +02:00
case kDMIconIndiceJunkJewelSymalUnequipped :
case kDMIconIndiceJunkJewelSymalEquipped :
2016-09-09 07:32:32 +02:00
statIndex = kDMStatAntimagic ;
2016-08-26 22:51:17 +02:00
modifier = 15 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceArmourCloakOfNight :
2016-09-09 07:32:32 +02:00
statIndex = kDMStatDexterity ;
2016-08-26 22:51:17 +02:00
modifier = 8 ;
break ;
2016-09-09 07:12:36 +02:00
case kDMIconIndiceJunkMoonstone :
2016-09-09 07:32:32 +02:00
statIndex = kDMStatMana ;
2016-08-26 22:51:17 +02:00
modifier = 3 ;
break ;
default :
break ;
}
}
}
if ( modifier ) {
modifier * = modifierFactor ;
//statIndex is set when modifier is set
2016-09-09 07:32:32 +02:00
if ( statIndex = = kDMStatMana ) {
2016-08-26 22:51:17 +02:00
champ - > _maxMana + = modifier ;
2016-09-09 07:32:32 +02:00
} else if ( statIndex < kDMStatAntifire + 1 ) {
for ( uint16 statValIndex = kDMStatMaximum ; statValIndex < = kDMStatMinimum ; + + statValIndex ) {
champ - > getStatistic ( ( ChampionStatType ) statIndex , ( ChampionStatValue ) statValIndex ) + = modifier ;
2016-08-26 22:51:17 +02:00
}
}
}
}
2016-08-23 07:54:16 +02:00
bool ChampionMan : : hasObjectIconInSlotBoxChanged ( int16 slotBoxIndex , Thing thing ) {
2016-08-26 22:51:17 +02:00
ObjectMan & objMan = * _vm - > _objectMan ;
2016-08-25 22:19:34 +02:00
IconIndice currIconIndex = objMan . getIconIndexInSlotBox ( slotBoxIndex ) ;
2016-09-09 07:12:36 +02:00
if ( ( ( currIconIndex < kDMIconIndiceWeaponDagger ) & & ( currIconIndex > = kDMIconIndiceJunkCompassNorth ) )
| | ( ( currIconIndex > = kDMIconIndicePotionMaPotionMonPotion ) & & ( currIconIndex < = kDMIconIndicePotionWaterFlask ) )
| | ( currIconIndex = = kDMIconIndicePotionEmptyFlask ) ) {
2016-08-25 22:19:34 +02:00
IconIndice newIconIndex = objMan . getIconIndex ( thing ) ;
2016-08-26 22:51:17 +02:00
if ( newIconIndex ! = currIconIndex ) {
2016-09-18 22:15:51 +02:00
if ( ( slotBoxIndex < kDMSlotBoxInventoryFirstSlot ) & & ! _mousePointerHiddenToDrawChangedObjIconOnScreen ) {
2016-08-23 07:54:16 +02:00
_mousePointerHiddenToDrawChangedObjIconOnScreen = true ;
2016-08-25 08:12:23 +02:00
_vm - > _eventMan - > hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-25 22:19:34 +02:00
objMan . drawIconInSlotBox ( slotBoxIndex , newIconIndex ) ;
2016-08-26 22:51:17 +02:00
return true ;
}
}
return false ;
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : drawChangedObjectIcons ( ) {
2016-08-26 22:51:17 +02:00
InventoryMan & invMan = * _vm - > _inventoryMan ;
ObjectMan & objMan = * _vm - > _objectMan ;
MenuMan & menuMan = * _vm - > _menuMan ;
2016-09-22 07:02:49 +02:00
EventManager & eventMan = * _vm - > _eventMan ;
2016-08-26 22:51:17 +02:00
2016-08-25 21:25:18 +02:00
uint16 invChampOrdinal = invMan . _inventoryChampionOrdinal ;
2016-08-23 07:54:16 +02:00
if ( _candidateChampionOrdinal & & ! invChampOrdinal )
2016-08-26 22:51:17 +02:00
return ;
2016-08-23 07:54:16 +02:00
_mousePointerHiddenToDrawChangedObjIconOnScreen = false ;
IconIndice leaderHandObjIconIndex = _leaderHandObjectIconIndex ;
2016-08-26 22:51:17 +02:00
2016-09-09 07:12:36 +02:00
if ( ( ( leaderHandObjIconIndex < kDMIconIndiceWeaponDagger ) & & ( leaderHandObjIconIndex > = kDMIconIndiceJunkCompassNorth ) ) // < instead of <= is correct
| | ( ( leaderHandObjIconIndex > = kDMIconIndicePotionMaPotionMonPotion ) & & ( leaderHandObjIconIndex < = kDMIconIndicePotionWaterFlask ) )
| | ( leaderHandObjIconIndex = = kDMIconIndicePotionEmptyFlask ) ) {
2016-08-25 22:19:34 +02:00
IconIndice iconIndex = objMan . getIconIndex ( _leaderHandObject ) ;
2016-08-26 22:51:17 +02:00
if ( iconIndex ! = leaderHandObjIconIndex ) {
2016-08-23 07:54:16 +02:00
_mousePointerHiddenToDrawChangedObjIconOnScreen = true ;
2016-09-22 07:02:49 +02:00
eventMan . hideMouse ( ) ;
2016-08-25 22:19:34 +02:00
objMan . extractIconFromBitmap ( iconIndex , objMan . _objectIconForMousePointer ) ;
2016-09-22 07:02:49 +02:00
eventMan . setPointerToObject ( _vm - > _objectMan - > _objectIconForMousePointer ) ;
2016-08-23 07:54:16 +02:00
_leaderHandObjectIconIndex = iconIndex ;
2016-08-25 22:19:34 +02:00
objMan . drawLeaderObjectName ( _leaderHandObject ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-08-23 07:54:16 +02:00
for ( uint16 slotBoxIndex = 0 ; slotBoxIndex < ( _partyChampionCount * 2 ) ; + + slotBoxIndex ) {
2016-08-26 22:51:17 +02:00
int16 champIndex = slotBoxIndex > > 1 ;
2016-08-23 23:36:18 +02:00
if ( invChampOrdinal = = _vm - > indexToOrdinal ( champIndex ) )
2016-08-26 22:51:17 +02:00
continue ;
2016-08-23 07:54:16 +02:00
if ( hasObjectIconInSlotBoxChanged ( slotBoxIndex , _champions [ champIndex ] . getSlot ( ( ChampionSlot ) getHandSlotIndex ( slotBoxIndex ) ) )
2016-09-10 11:47:36 +02:00
& & ( getHandSlotIndex ( slotBoxIndex ) = = kDMSlotActionHand ) ) {
2016-08-26 22:51:17 +02:00
2016-08-25 21:59:02 +02:00
menuMan . drawActionIcon ( ( ChampionIndex ) champIndex ) ;
2016-08-26 22:51:17 +02:00
}
}
if ( invChampOrdinal ) {
2016-08-23 23:36:18 +02:00
Champion * champ = & _champions [ _vm - > ordinalToIndex ( invChampOrdinal ) ] ;
2016-09-10 11:47:36 +02:00
Thing * thing = & champ - > getSlot ( kDMSlotReadyHand ) ;
2016-08-26 22:51:17 +02:00
uint16 drawViewport = 0 ;
2016-09-10 11:47:36 +02:00
for ( uint16 slotIndex = kDMSlotReadyHand ; slotIndex < kDMSlotChest1 ; slotIndex + + , thing + + ) {
2016-09-18 22:15:51 +02:00
uint16 objIconChanged = hasObjectIconInSlotBoxChanged ( slotIndex + kDMSlotBoxInventoryFirstSlot , * thing ) ? 1 : 0 ;
2016-08-26 22:51:17 +02:00
drawViewport | = objIconChanged ;
2016-09-10 11:47:36 +02:00
if ( objIconChanged & & ( slotIndex = = kDMSlotActionHand ) ) {
2016-08-25 21:59:02 +02:00
menuMan . drawActionIcon ( ( ChampionIndex ) _vm - > ordinalToIndex ( invChampOrdinal ) ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-09-18 11:46:53 +02:00
if ( invMan . _panelContent = = kDMPanelContentChest ) {
2016-08-25 21:25:18 +02:00
thing = invMan . _chestSlots ;
2016-08-26 22:51:17 +02:00
for ( int16 slotIndex = 0 ; slotIndex < 8 ; + + slotIndex , thing + + ) {
2016-09-18 11:46:53 +02:00
drawViewport | = ( hasObjectIconInSlotBoxChanged ( slotIndex + kDMSlotBoxChestFirstSlot , * thing ) ? 1 : 0 ) ;
2016-08-26 22:51:17 +02:00
}
}
if ( drawViewport ) {
2016-09-09 07:32:32 +02:00
champ - > setAttributeFlag ( kDMAttributeViewport , true ) ;
2016-08-23 23:36:18 +02:00
drawChampionState ( ( ChampionIndex ) _vm - > ordinalToIndex ( invChampOrdinal ) ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-08-23 07:54:16 +02:00
if ( _mousePointerHiddenToDrawChangedObjIconOnScreen )
2016-09-22 07:02:49 +02:00
eventMan . showMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : addObjectInSlot ( ChampionIndex champIndex , Thing thing , ChampionSlot slotIndex ) {
2017-01-31 18:15:31 +01:00
if ( thing = = _vm - > _thingNone )
2016-09-22 07:02:49 +02:00
return ;
2016-08-26 22:51:17 +02:00
InventoryMan & invMan = * _vm - > _inventoryMan ;
DungeonMan & dunMan = * _vm - > _dungeonMan ;
ObjectMan & objMan = * _vm - > _objectMan ;
MenuMan & menuMan = * _vm - > _menuMan ;
2016-08-23 07:54:16 +02:00
Champion * champ = & _champions [ champIndex ] ;
2016-08-26 22:51:17 +02:00
2016-09-22 07:02:49 +02:00
if ( slotIndex > = kDMSlotChest1 )
2016-09-10 11:47:36 +02:00
invMan . _chestSlots [ slotIndex - kDMSlotChest1 ] = thing ;
2016-09-22 07:02:49 +02:00
else
2016-08-26 22:51:17 +02:00
champ - > setSlot ( slotIndex , thing ) ;
2016-08-24 08:03:55 +02:00
champ - > _load + = dunMan . getObjectWeight ( thing ) ;
2016-09-09 07:32:32 +02:00
champ - > setAttributeFlag ( kDMAttributeLoad , true ) ;
2016-08-25 22:19:34 +02:00
IconIndice iconIndex = objMan . getIconIndex ( thing ) ;
2016-08-25 21:25:18 +02:00
bool isInventoryChampion = ( _vm - > indexToOrdinal ( champIndex ) = = invMan . _inventoryChampionOrdinal ) ;
2016-08-23 07:54:16 +02:00
applyModifiersToStatistics ( champ , slotIndex , iconIndex , 1 , thing ) ;
2016-08-24 08:03:55 +02:00
uint16 * rawObjPtr = dunMan . getThingData ( thing ) ;
2016-08-26 22:51:17 +02:00
2016-09-10 11:47:36 +02:00
if ( slotIndex < kDMSlotHead ) {
if ( slotIndex = = kDMSlotActionHand ) {
2016-09-09 07:32:32 +02:00
champ - > setAttributeFlag ( kDMAttributeActionHand , true ) ;
2016-08-23 23:36:18 +02:00
if ( _actingChampionOrdinal = = _vm - > indexToOrdinal ( champIndex ) )
2016-08-25 21:59:02 +02:00
menuMan . clearActingChampion ( ) ;
2016-08-26 22:51:17 +02:00
2016-09-09 07:12:36 +02:00
if ( ( iconIndex > = kDMIconIndiceScrollOpen ) & & ( iconIndex < = kDMIconIndiceScrollClosed ) ) {
2016-08-26 22:51:17 +02:00
( ( Scroll * ) rawObjPtr ) - > setClosed ( false ) ;
2016-08-23 07:54:16 +02:00
drawChangedObjectIcons ( ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-09-09 07:12:36 +02:00
if ( iconIndex = = kDMIconIndiceWeaponTorchUnlit ) {
2016-08-26 22:51:17 +02:00
( ( Weapon * ) rawObjPtr ) - > setLit ( true ) ;
2016-09-22 07:02:49 +02:00
invMan . setDungeonViewPalette ( ) ;
2016-08-23 07:54:16 +02:00
drawChangedObjectIcons ( ) ;
2016-09-10 11:47:36 +02:00
} else if ( isInventoryChampion & & ( slotIndex = = kDMSlotActionHand ) & &
2016-09-09 07:12:36 +02:00
( ( iconIndex = = kDMIconIndiceContainerChestClosed ) | | ( ( iconIndex > = kDMIconIndiceScrollOpen ) & & ( iconIndex < = kDMIconIndiceScrollClosed ) ) ) ) {
2016-09-09 07:32:32 +02:00
champ - > setAttributeFlag ( kDMAttributePanel , true ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-10 11:47:36 +02:00
} else if ( slotIndex = = kDMSlotNeck ) {
2016-09-09 07:12:36 +02:00
if ( ( iconIndex > = kDMIconIndiceJunkIllumuletUnequipped ) & & ( iconIndex < = kDMIconIndiceJunkIllumuletEquipped ) ) {
2016-08-26 22:51:17 +02:00
( ( Junk * ) rawObjPtr ) - > setChargeCount ( 1 ) ;
2016-08-23 07:54:16 +02:00
_party . _magicalLightAmount + = _lightPowerToLightAmount [ 2 ] ;
2016-09-22 07:02:49 +02:00
invMan . setDungeonViewPalette ( ) ;
2016-08-26 22:51:17 +02:00
iconIndex = ( IconIndice ) ( iconIndex + 1 ) ;
2016-09-09 07:12:36 +02:00
} else if ( ( iconIndex > = kDMIconIndiceJunkJewelSymalUnequipped ) & & ( iconIndex < = kDMIconIndiceJunkJewelSymalEquipped ) ) {
2016-08-26 22:51:17 +02:00
( ( Junk * ) rawObjPtr ) - > setChargeCount ( 1 ) ;
iconIndex = ( IconIndice ) ( iconIndex + 1 ) ;
}
}
2016-08-23 07:54:16 +02:00
drawSlot ( champIndex , slotIndex ) ;
2016-08-26 22:51:17 +02:00
if ( isInventoryChampion )
2016-09-09 07:32:32 +02:00
champ - > setAttributeFlag ( kDMAttributeViewport , true ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
int16 ChampionMan : : getScentOrdinal ( int16 mapX , int16 mapY ) {
int16 scentIndex = _party . _scentCount ;
2016-08-26 22:51:17 +02:00
if ( scentIndex ) {
Scent searchedScent ;
searchedScent . setMapX ( mapX ) ;
searchedScent . setMapY ( mapY ) ;
2016-08-24 08:03:55 +02:00
searchedScent . setMapIndex ( _vm - > _dungeonMan - > _currMapIndex ) ;
2016-08-26 22:51:17 +02:00
uint16 searchedScentRedEagle = searchedScent . toUint16 ( ) ;
2016-08-23 07:54:16 +02:00
Scent * scent = & _party . _scents [ scentIndex - - ] ;
2016-08-26 22:51:17 +02:00
do {
2016-09-22 07:02:49 +02:00
if ( ( * ( - - scent ) ) . toUint16 ( ) = = searchedScentRedEagle )
2016-08-23 23:36:18 +02:00
return _vm - > indexToOrdinal ( scentIndex ) ;
2016-08-26 22:51:17 +02:00
} while ( scentIndex - - ) ;
}
return 0 ;
}
2016-08-23 07:54:16 +02:00
Thing ChampionMan : : getObjectRemovedFromLeaderHand ( ) {
2016-09-22 07:02:49 +02:00
EventManager & eventMan = * _vm - > _eventMan ;
2016-08-23 07:54:16 +02:00
_leaderEmptyHanded = true ;
Thing leaderHandObject = _leaderHandObject ;
2016-08-26 22:51:17 +02:00
2017-01-31 18:15:31 +01:00
if ( leaderHandObject ! = _vm - > _thingNone ) {
_leaderHandObject = _vm - > _thingNone ;
2016-09-09 07:12:36 +02:00
_leaderHandObjectIconIndex = kDMIconIndiceNone ;
2016-09-22 07:02:49 +02:00
eventMan . showMouse ( ) ;
2016-08-25 22:19:34 +02:00
_vm - > _objectMan - > clearLeaderObjectName ( ) ;
2016-09-22 07:02:49 +02:00
eventMan . setMousePointer ( ) ;
eventMan . hideMouse ( ) ;
2016-09-09 07:12:36 +02:00
if ( _leaderIndex ! = kDMChampionNone ) {
2016-08-24 08:03:55 +02:00
_champions [ _leaderIndex ] . _load - = _vm - > _dungeonMan - > getObjectWeight ( leaderHandObject ) ;
2016-09-09 07:32:32 +02:00
setFlag ( _champions [ _leaderIndex ] . _attributes , kDMAttributeLoad ) ;
2016-08-23 07:54:16 +02:00
drawChampionState ( _leaderIndex ) ;
2016-08-26 22:51:17 +02:00
}
}
return leaderHandObject ;
}
2016-08-23 07:54:16 +02:00
uint16 ChampionMan : : getStrength ( int16 champIndex , int16 slotIndex ) {
Champion * curChampion = & _champions [ champIndex ] ;
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-09-09 07:32:32 +02:00
int16 strength = _vm - > getRandomNumber ( 16 ) + curChampion - > _statistics [ kDMStatStrength ] [ kDMStatCurrent ] ;
2016-08-26 22:51:17 +02:00
Thing curThing = curChampion - > _slots [ slotIndex ] ;
2016-09-23 07:52:53 +02:00
uint16 objectWeight = dungeon . getObjectWeight ( curThing ) ;
2016-08-23 07:54:16 +02:00
uint16 oneSixteenthMaximumLoad = getMaximumLoad ( curChampion ) > > 4 ;
2016-08-26 22:51:17 +02:00
2016-09-22 07:02:49 +02:00
if ( objectWeight < = oneSixteenthMaximumLoad )
2016-08-26 22:51:17 +02:00
strength + = objectWeight - 12 ;
2016-09-22 07:02:49 +02:00
else {
2016-08-26 22:51:17 +02:00
int16 loadThreshold = oneSixteenthMaximumLoad + ( ( oneSixteenthMaximumLoad - 12 ) > > 1 ) ;
2016-09-22 07:02:49 +02:00
if ( objectWeight < = loadThreshold )
2016-08-26 22:51:17 +02:00
strength + = ( objectWeight - oneSixteenthMaximumLoad ) > > 1 ;
2016-09-22 07:02:49 +02:00
else
2016-08-26 22:51:17 +02:00
strength - = ( objectWeight - loadThreshold ) < < 1 ;
}
2016-09-22 07:02:49 +02:00
2016-09-11 00:33:54 +02:00
if ( curThing . getType ( ) = = kDMThingTypeWeapon ) {
2016-09-23 07:52:53 +02:00
WeaponInfo * weaponInfo = dungeon . getWeaponInfo ( curThing ) ;
2016-08-26 22:51:17 +02:00
strength + = weaponInfo - > _strength ;
uint16 skillLevel = 0 ;
uint16 weaponClass = weaponInfo - > _class ;
2016-09-22 07:02:49 +02:00
if ( ( weaponClass = = kDMWeaponClassSwingWeapon ) | | ( weaponClass = = kDMWeaponClassDaggerAndAxes ) )
2016-09-09 07:32:32 +02:00
skillLevel = getSkillLevel ( champIndex , kDMSkillSwing ) ;
2016-09-22 07:02:49 +02:00
if ( ( weaponClass ! = kDMWeaponClassSwingWeapon ) & & ( weaponClass < kDMWeaponClassFirstBow ) )
2016-09-09 07:32:32 +02:00
skillLevel + = getSkillLevel ( champIndex , kDMSkillThrow ) ;
2016-09-22 07:02:49 +02:00
if ( ( weaponClass > = kDMWeaponClassFirstBow ) & & ( weaponClass < kDMWeaponClassFirstMagicWeapon ) )
2016-09-09 07:32:32 +02:00
skillLevel + = getSkillLevel ( champIndex , kDMSkillShoot ) ;
2016-09-22 07:02:49 +02:00
2016-08-26 22:51:17 +02:00
strength + = skillLevel < < 1 ;
}
2016-08-23 07:54:16 +02:00
strength = getStaminaAdjustedValue ( curChampion , strength ) ;
2016-09-22 07:02:49 +02:00
if ( getFlag ( curChampion - > _wounds , ( slotIndex = = kDMSlotReadyHand ) ? kDMWoundReadHand : kDMWoundActionHand ) )
2016-08-26 22:51:17 +02:00
strength > > = 1 ;
2016-09-22 07:02:49 +02:00
2016-09-11 11:10:22 +02:00
return CLIP ( 0 , strength > > 1 , 100 ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
Thing ChampionMan : : getObjectRemovedFromSlot ( uint16 champIndex , uint16 slotIndex ) {
Champion * curChampion = & _champions [ champIndex ] ;
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-09-26 21:12:51 +02:00
InventoryMan & inventory = * _vm - > _inventoryMan ;
2016-08-26 22:51:17 +02:00
Thing curThing ;
2016-09-10 11:47:36 +02:00
if ( slotIndex > = kDMSlotChest1 ) {
2016-09-26 21:12:51 +02:00
curThing = inventory . _chestSlots [ slotIndex - kDMSlotChest1 ] ;
2017-01-31 18:15:31 +01:00
inventory . _chestSlots [ slotIndex - kDMSlotChest1 ] = _vm - > _thingNone ;
2016-08-26 22:51:17 +02:00
} else {
curThing = curChampion - > _slots [ slotIndex ] ;
2017-01-31 18:15:31 +01:00
curChampion - > _slots [ slotIndex ] = _vm - > _thingNone ;
2016-08-26 22:51:17 +02:00
}
2017-01-31 18:15:31 +01:00
if ( curThing = = _vm - > _thingNone )
return _vm - > _thingNone ;
2016-08-26 22:51:17 +02:00
2016-09-26 21:12:51 +02:00
bool isInventoryChampion = ( _vm - > indexToOrdinal ( champIndex ) = = inventory . _inventoryChampionOrdinal ) ;
2016-08-25 22:19:34 +02:00
int16 curIconIndex = _vm - > _objectMan - > getIconIndex ( curThing ) ;
2016-08-26 22:51:17 +02:00
// Remove object modifiers
2016-08-23 07:54:16 +02:00
applyModifiersToStatistics ( curChampion , slotIndex , curIconIndex , - 1 , curThing ) ;
2016-08-26 22:51:17 +02:00
2016-09-23 07:52:53 +02:00
Weapon * curWeapon = ( Weapon * ) dungeon . getThingData ( curThing ) ;
2016-09-10 11:47:36 +02:00
if ( slotIndex = = kDMSlotNeck ) {
2016-09-09 07:12:36 +02:00
if ( ( curIconIndex > = kDMIconIndiceJunkIllumuletUnequipped ) & & ( curIconIndex < = kDMIconIndiceJunkIllumuletEquipped ) ) {
2016-08-26 22:51:17 +02:00
( ( Junk * ) curWeapon ) - > setChargeCount ( 0 ) ;
2016-08-23 07:54:16 +02:00
_party . _magicalLightAmount - = _lightPowerToLightAmount [ 2 ] ;
2016-09-26 21:12:51 +02:00
inventory . setDungeonViewPalette ( ) ;
2016-09-09 07:12:36 +02:00
} else if ( ( curIconIndex > = kDMIconIndiceJunkJewelSymalUnequipped ) & & ( curIconIndex < = kDMIconIndiceJunkJewelSymalEquipped ) ) {
2016-08-26 22:51:17 +02:00
( ( Junk * ) curWeapon ) - > setChargeCount ( 0 ) ;
}
}
2016-08-23 07:54:16 +02:00
drawSlot ( champIndex , slotIndex ) ;
2016-08-26 22:51:17 +02:00
if ( isInventoryChampion )
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeViewport ) ;
2016-08-26 22:51:17 +02:00
2016-09-10 11:47:36 +02:00
if ( slotIndex < kDMSlotHead ) {
if ( slotIndex = = kDMSlotActionHand ) {
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeActionHand ) ;
2016-08-23 23:36:18 +02:00
if ( _actingChampionOrdinal = = _vm - > indexToOrdinal ( champIndex ) )
2016-08-25 21:59:02 +02:00
_vm - > _menuMan - > clearActingChampion ( ) ;
2016-08-26 22:51:17 +02:00
2016-09-09 07:12:36 +02:00
if ( ( curIconIndex > = kDMIconIndiceScrollOpen ) & & ( curIconIndex < = kDMIconIndiceScrollClosed ) ) {
2016-08-26 22:51:17 +02:00
( ( Scroll * ) curWeapon ) - > setClosed ( true ) ;
2016-08-23 07:54:16 +02:00
drawChangedObjectIcons ( ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-09-09 07:12:36 +02:00
if ( ( curIconIndex > = kDMIconIndiceWeaponTorchUnlit ) & & ( curIconIndex < = kDMIconIndiceWeaponTorchLit ) ) {
2016-08-26 22:51:17 +02:00
curWeapon - > setLit ( false ) ;
2016-09-26 21:12:51 +02:00
inventory . setDungeonViewPalette ( ) ;
2016-08-23 07:54:16 +02:00
drawChangedObjectIcons ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-10 11:47:36 +02:00
if ( isInventoryChampion & & ( slotIndex = = kDMSlotActionHand ) ) {
2016-08-26 22:51:17 +02:00
switch ( curIconIndex ) {
2016-09-09 07:12:36 +02:00
case kDMIconIndiceContainerChestClosed :
2016-09-26 21:12:51 +02:00
inventory . closeChest ( ) ;
2017-08-06 12:26:05 +02:00
// fall through
2016-09-09 07:12:36 +02:00
case kDMIconIndiceScrollOpen :
case kDMIconIndiceScrollClosed :
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributePanel ) ;
2016-08-26 22:51:17 +02:00
break ;
default :
break ;
}
}
}
2016-09-23 07:52:53 +02:00
curChampion - > _load - = dungeon . getObjectWeight ( curThing ) ;
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeLoad ) ;
2016-08-26 22:51:17 +02:00
return curThing ;
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : decrementStamina ( int16 championIndex , int16 decrement ) {
2016-09-09 07:12:36 +02:00
if ( championIndex = = kDMChampionNone )
2016-08-26 22:51:17 +02:00
return ;
2016-08-23 07:54:16 +02:00
Champion * curChampion = & _champions [ championIndex ] ;
2016-08-26 22:51:17 +02:00
curChampion - > _currStamina - = decrement ;
int16 stamina = curChampion - > _currStamina ;
if ( stamina < = 0 ) {
curChampion - > _currStamina = 0 ;
2016-09-10 14:31:49 +02:00
addPendingDamageAndWounds_getDamage ( championIndex , ( - stamina ) > > 1 , kDMWoundNone , kDMAttackTypeNormal ) ;
2016-09-23 07:52:53 +02:00
} else if ( stamina > curChampion - > _maxStamina )
2016-08-26 22:51:17 +02:00
curChampion - > _currStamina = curChampion - > _maxStamina ;
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeLoad | kDMAttributeStatistics ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
int16 ChampionMan : : addPendingDamageAndWounds_getDamage ( int16 champIndex , int16 attack , int16 allowedWounds , uint16 attackType ) {
2016-08-26 22:51:17 +02:00
if ( attack < = 0 )
return 0 ;
2016-08-23 07:54:16 +02:00
Champion * curChampion = & _champions [ champIndex ] ;
2016-08-26 22:51:17 +02:00
if ( ! curChampion - > _currHealth )
return 0 ;
2016-09-10 14:31:49 +02:00
if ( attackType ! = kDMAttackTypeNormal ) {
2016-08-26 22:51:17 +02:00
uint16 defense = 0 ;
uint16 woundCount = 0 ;
2016-09-10 11:47:36 +02:00
for ( int16 woundIndex = kDMSlotReadyHand ; woundIndex < = kDMSlotFeet ; woundIndex + + ) {
2016-08-26 22:51:17 +02:00
if ( allowedWounds & ( 1 < < woundIndex ) ) {
woundCount + + ;
2016-09-10 14:53:10 +02:00
defense + = getWoundDefense ( champIndex , woundIndex | ( ( attackType = = kDMAttackTypeSharp ) ? kDMMaskSharpDefense : kDMMaskNoSharpDefense ) ) ;
2016-08-26 22:51:17 +02:00
}
}
if ( woundCount )
defense / = woundCount ;
2016-08-20 10:17:53 +02:00
bool skipScaling = false ;
2016-08-26 22:51:17 +02:00
switch ( attackType ) {
2016-09-10 14:31:49 +02:00
case kDMAttackTypePsychic :
2016-08-26 22:51:17 +02:00
{
2016-09-09 07:32:32 +02:00
int16 wisdomFactor = 115 - curChampion - > _statistics [ kDMStatWisdom ] [ kDMStatCurrent ] ;
2016-09-23 07:52:53 +02:00
if ( wisdomFactor < = 0 )
2016-08-26 22:51:17 +02:00
attack = 0 ;
2016-09-23 07:52:53 +02:00
else
2016-08-23 23:36:18 +02:00
attack = _vm - > getScaledProduct ( attack , 6 , wisdomFactor ) ;
2016-08-26 22:51:17 +02:00
skipScaling = true ;
}
break ;
2016-09-10 14:31:49 +02:00
case kDMAttackTypeMagic :
2016-09-09 07:32:32 +02:00
attack = getStatisticAdjustedAttack ( curChampion , kDMStatAntimagic , attack ) ;
2016-08-23 07:54:16 +02:00
attack - = _party . _spellShieldDefense ;
2016-08-26 22:51:17 +02:00
skipScaling = true ;
break ;
2016-09-10 14:31:49 +02:00
case kDMAttackTypeFire :
2016-09-09 07:32:32 +02:00
attack = getStatisticAdjustedAttack ( curChampion , kDMStatAntifire , attack ) ;
2016-08-23 07:54:16 +02:00
attack - = _party . _fireShieldDefense ;
2016-08-26 22:51:17 +02:00
break ;
2016-09-10 14:31:49 +02:00
case kDMAttackTypeSelf :
2016-08-26 22:51:17 +02:00
defense > > = 1 ;
break ;
default :
break ;
}
if ( ! skipScaling ) {
if ( attack < = 0 )
return 0 ;
2016-08-23 23:36:18 +02:00
attack = _vm - > getScaledProduct ( attack , 6 , 130 - defense ) ;
2016-08-26 22:51:17 +02:00
}
/* 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 ;
2016-09-09 07:32:32 +02:00
int16 adjustedAttack = getStatisticAdjustedAttack ( curChampion , kDMStatVitality , _vm - > getRandomNumber ( 128 ) + 10 ) ;
2016-08-26 22:51:17 +02:00
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 {
2016-08-23 07:54:16 +02:00
setFlag ( * ( uint16 * ) & _championPendingWounds [ champIndex ] , ( 1 < < _vm - > getRandomNumber ( 8 ) ) & allowedWounds ) ;
2016-08-26 22:51:17 +02:00
} while ( ( attack > ( adjustedAttack < < = 1 ) ) & & adjustedAttack ) ;
}
2016-08-23 07:54:16 +02:00
if ( _partyIsSleeping )
wakeUp ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
_championPendingDamage [ champIndex ] + = attack ;
2016-08-26 22:51:17 +02:00
return attack ;
}
2016-08-23 07:54:16 +02:00
int16 ChampionMan : : getWoundDefense ( int16 champIndex , uint16 woundIndex ) {
2016-08-26 22:51:17 +02:00
static const byte woundDefenseFactor [ 6 ] = { 5 , 5 , 4 , 6 , 3 , 1 } ; // @ G0050_auc_Graphic562_WoundDefenseFactor
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-08-23 07:54:16 +02:00
Champion * curChampion = & _champions [ champIndex ] ;
2016-09-10 14:53:10 +02:00
bool useSharpDefense = getFlag ( woundIndex , kDMMaskSharpDefense ) ;
2016-08-26 22:51:17 +02:00
if ( useSharpDefense )
2016-09-10 14:53:10 +02:00
clearFlag ( woundIndex , kDMMaskSharpDefense ) ;
2016-08-26 22:51:17 +02:00
uint16 armorShieldDefense = 0 ;
2016-09-10 11:47:36 +02:00
for ( int16 slotIndex = kDMSlotReadyHand ; slotIndex < = kDMSlotActionHand ; slotIndex + + ) {
2016-08-26 22:51:17 +02:00
Thing curThing = curChampion - > _slots [ slotIndex ] ;
2016-09-11 00:33:54 +02:00
if ( curThing . getType ( ) = = kDMThingTypeArmour ) {
2016-09-23 07:52:53 +02:00
ArmourInfo * armorInfo = ( ArmourInfo * ) dungeon . getThingData ( curThing ) ;
armorInfo = & dungeon . _armourInfos [ ( ( Armour * ) armorInfo ) - > getType ( ) ] ;
2016-09-11 23:06:29 +02:00
if ( getFlag ( armorInfo - > _attributes , kDMArmourAttributeShield ) )
2016-09-23 07:52:53 +02:00
armorShieldDefense + = ( ( getStrength ( champIndex , slotIndex ) + dungeon . getArmourDefense ( armorInfo , useSharpDefense ) ) * woundDefenseFactor [ woundIndex ] ) > > ( ( slotIndex = = woundIndex ) ? 4 : 5 ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-09-09 07:32:32 +02:00
int16 woundDefense = _vm - > getRandomNumber ( ( curChampion - > _statistics [ kDMStatVitality ] [ kDMStatCurrent ] > > 3 ) + 1 ) ;
2016-08-26 22:51:17 +02:00
if ( useSharpDefense )
woundDefense > > = 1 ;
2016-08-23 07:54:16 +02:00
woundDefense + = curChampion - > _actionDefense + curChampion - > _shieldDefense + _party . _shieldDefense + armorShieldDefense ;
2016-09-10 11:47:36 +02:00
if ( woundIndex > kDMSlotActionHand ) {
2016-08-26 22:51:17 +02:00
Thing curThing = curChampion - > _slots [ woundIndex ] ;
2016-09-11 00:33:54 +02:00
if ( curThing . getType ( ) = = kDMThingTypeArmour ) {
2016-09-23 07:52:53 +02:00
ArmourInfo * armourInfo = ( ArmourInfo * ) dungeon . getThingData ( curThing ) ;
woundDefense + = dungeon . getArmourDefense ( & dungeon . _armourInfos [ ( ( Armour * ) armourInfo ) - > getType ( ) ] , useSharpDefense ) ;
2016-08-26 22:51:17 +02:00
}
}
if ( getFlag ( curChampion - > _wounds , 1 < < woundIndex ) )
woundDefense - = 8 + _vm - > getRandomNumber ( 4 ) ;
2016-08-23 07:54:16 +02:00
if ( _partyIsSleeping )
2016-08-26 22:51:17 +02:00
woundDefense > > = 1 ;
2016-09-11 11:10:22 +02:00
return CLIP ( 0 , woundDefense > > 1 , 100 ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
uint16 ChampionMan : : getStatisticAdjustedAttack ( Champion * champ , uint16 statIndex , uint16 attack ) {
2016-09-09 07:32:32 +02:00
int16 factor = 170 - champ - > _statistics [ statIndex ] [ kDMStatCurrent ] ;
2016-08-26 22:51:17 +02:00
/* 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 ;
2016-08-23 23:36:18 +02:00
return _vm - > getScaledProduct ( attack , 7 , factor ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : wakeUp ( ) {
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
2016-08-23 23:36:18 +02:00
_vm - > _stopWaitingForPlayerInput = true ;
2016-08-23 07:54:16 +02:00
_partyIsSleeping = false ;
2016-08-23 23:36:18 +02:00
_vm - > _waitForInputMaxVerticalBlankCount = 10 ;
_vm - > delay ( 10 ) ;
2016-08-25 18:32:03 +02:00
_vm - > _displayMan - > drawFloorAndCeiling ( ) ;
2016-09-25 07:42:35 +02:00
evtMan . _primaryMouseInput = evtMan . _primaryMouseInputInterface ;
evtMan . _secondaryMouseInput = evtMan . _secondaryMouseInputMovement ;
evtMan . _primaryKeyboardInput = evtMan . _primaryKeyboardInputInterface ;
evtMan . _secondaryKeyboardInput = evtMan . _secondaryKeyboardInputMovement ;
evtMan . discardAllInput ( ) ;
2016-08-25 21:59:02 +02:00
_vm - > _menuMan - > drawEnabledMenus ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
int16 ChampionMan : : getThrowingStaminaCost ( Thing thing ) {
2016-08-24 08:03:55 +02:00
int16 weight = _vm - > _dungeonMan - > getObjectWeight ( thing ) > > 1 ;
2016-09-11 11:10:22 +02:00
int16 staminaCost = CLIP < int16 > ( 1 , weight , 10 ) ;
2016-08-26 22:51:17 +02:00
while ( ( weight - = 10 ) > 0 )
staminaCost + = weight > > 1 ;
return staminaCost ;
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : disableAction ( uint16 champIndex , uint16 ticks ) {
Champion * curChampion = & _champions [ champIndex ] ;
2016-08-23 23:36:18 +02:00
int32 updatedEnableActionEventTime = _vm - > _gameTime + ticks ;
2016-08-26 22:51:17 +02:00
TimelineEvent curEvent ;
2016-09-20 21:51:42 +02:00
curEvent . _type = kDMEventTypeEnableChampionAction ;
2016-08-26 22:51:17 +02:00
curEvent . _priority = champIndex ;
2016-09-10 21:50:57 +02:00
curEvent . _Bu . _slotOrdinal = 0 ;
2016-08-26 22:51:17 +02:00
int16 eventIndex = curChampion - > _enableActionEventIndex ;
if ( eventIndex > = 0 ) {
2016-09-11 09:46:35 +02:00
int32 currentEnableActionEventTime = _vm - > filterTime ( _vm - > _timeline - > _events [ eventIndex ] . _mapTime ) ;
2016-09-23 07:52:53 +02:00
if ( updatedEnableActionEventTime > = currentEnableActionEventTime )
2016-08-23 23:36:18 +02:00
updatedEnableActionEventTime + = ( currentEnableActionEventTime - _vm - > _gameTime ) > > 1 ;
2016-09-23 07:52:53 +02:00
else
2016-08-26 22:51:17 +02:00
updatedEnableActionEventTime = currentEnableActionEventTime + ( ticks > > 1 ) ;
2016-08-25 22:38:03 +02:00
_vm - > _timeline - > deleteEvent ( eventIndex ) ;
2016-08-26 22:51:17 +02:00
} else {
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeActionHand | kDMAttributeDisableAction ) ;
2016-08-23 07:54:16 +02:00
drawChampionState ( ( ChampionIndex ) champIndex ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-19 07:05:37 +02:00
curEvent . _mapTime = _vm - > setMapAndTime ( _vm - > _dungeonMan - > _partyMapIndex , updatedEnableActionEventTime ) ;
2016-08-25 22:38:03 +02:00
curChampion - > _enableActionEventIndex = _vm - > _timeline - > addEventGetEventIndex ( & curEvent ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : addSkillExperience ( uint16 champIndex , uint16 skillIndex , uint16 exp ) {
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-09-25 07:42:35 +02:00
TextMan & txtMan = * _vm - > _textMan ;
2016-09-09 07:32:32 +02:00
if ( ( skillIndex > = kDMSkillSwing ) & & ( skillIndex < = kDMSkillShoot ) & & ( _vm - > _projexpl - > _lastCreatureAttackTime < _vm - > _gameTime - 150 ) )
2016-08-26 22:51:17 +02:00
exp > > = 1 ;
if ( exp ) {
2016-09-23 07:52:53 +02:00
if ( dungeon . _currMap - > _difficulty )
exp * = dungeon . _currMap - > _difficulty ;
2016-08-26 22:51:17 +02:00
2016-08-23 07:54:16 +02:00
Champion * curChampion = & _champions [ champIndex ] ;
2016-08-26 22:51:17 +02:00
uint16 baseSkillIndex ;
2016-09-09 07:32:32 +02:00
if ( skillIndex > = kDMSkillSwing )
baseSkillIndex = ( skillIndex - kDMSkillSwing ) > > 2 ;
2016-08-26 22:51:17 +02:00
else
baseSkillIndex = skillIndex ;
2016-09-09 07:12:36 +02:00
uint16 skillLevelBefore = getSkillLevel ( champIndex , baseSkillIndex | ( kDMIgnoreObjectModifiers | kDMIgnoreTemporaryExperience ) ) ;
2016-08-26 22:51:17 +02:00
2016-09-09 07:32:32 +02:00
if ( ( skillIndex > = kDMSkillSwing ) & & ( _vm - > _projexpl - > _lastCreatureAttackTime > _vm - > _gameTime - 25 ) )
2016-08-26 22:51:17 +02:00
exp < < = 1 ;
Skill * curSkill = & curChampion - > _skills [ skillIndex ] ;
curSkill - > _experience + = exp ;
if ( curSkill - > _temporaryExperience < 32000 )
2016-09-11 11:10:22 +02:00
curSkill - > _temporaryExperience + = CLIP ( 1 , exp > > 3 , 100 ) ;
2016-08-26 22:51:17 +02:00
curSkill = & curChampion - > _skills [ baseSkillIndex ] ;
2016-09-09 07:32:32 +02:00
if ( skillIndex > = kDMSkillSwing )
2016-08-26 22:51:17 +02:00
curSkill - > _experience + = exp ;
2016-09-09 07:12:36 +02:00
uint16 skillLevelAfter = getSkillLevel ( champIndex , baseSkillIndex | ( kDMIgnoreObjectModifiers | kDMIgnoreTemporaryExperience ) ) ;
2016-08-26 22:51:17 +02:00
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 */
2016-09-09 07:32:32 +02:00
if ( baseSkillIndex ! = kDMSkillPriest ) {
2016-08-26 22:51:17 +02:00
vitalityAmount & = skillLevelAfter ; /* For non Priest skills the amount is 0 for even skill levels. The amount is 0 or 1 for odd skill levels */
}
2016-09-09 07:32:32 +02:00
curChampion - > _statistics [ kDMStatVitality ] [ kDMStatMaximum ] + = vitalityAmount ;
2016-08-26 22:51:17 +02:00
uint16 staminaAmount = curChampion - > _maxStamina ;
2016-09-09 07:32:32 +02:00
curChampion - > _statistics [ kDMStatAntifire ] [ kDMStatMaximum ] + = _vm - > getRandomNumber ( 2 ) & ~ skillLevelAfter ; /* The amount is 0 for odd skill levels. The amount is 0 or 1 for even skill levels */
2016-08-26 22:51:17 +02:00
bool increaseManaFl = false ;
switch ( baseSkillIndex ) {
2016-09-09 07:32:32 +02:00
case kDMSkillFighter :
2016-08-26 22:51:17 +02:00
staminaAmount > > = 4 ;
skillLevelAfter * = 3 ;
2016-09-09 07:32:32 +02:00
curChampion - > _statistics [ kDMStatStrength ] [ kDMStatMaximum ] + = majorStatIncrease ;
curChampion - > _statistics [ kDMStatDexterity ] [ kDMStatMaximum ] + = minorStatIncrease ;
2016-08-26 22:51:17 +02:00
break ;
2016-09-09 07:32:32 +02:00
case kDMSkillNinja :
2016-08-26 22:51:17 +02:00
staminaAmount / = 21 ;
skillLevelAfter < < = 1 ;
2016-09-09 07:32:32 +02:00
curChampion - > _statistics [ kDMStatStrength ] [ kDMStatMaximum ] + = minorStatIncrease ;
curChampion - > _statistics [ kDMStatDexterity ] [ kDMStatMaximum ] + = majorStatIncrease ;
2016-08-26 22:51:17 +02:00
break ;
2016-09-09 07:32:32 +02:00
case kDMSkillWizard :
2016-08-26 22:51:17 +02:00
staminaAmount > > = 5 ;
curChampion - > _maxMana + = skillLevelAfter + ( skillLevelAfter > > 1 ) ;
2016-09-09 07:32:32 +02:00
curChampion - > _statistics [ kDMStatWisdom ] [ kDMStatMaximum ] + = majorStatIncrease ;
2016-08-26 22:51:17 +02:00
increaseManaFl = true ;
break ;
2016-09-09 07:32:32 +02:00
case kDMSkillPriest :
2016-08-26 22:51:17 +02:00
staminaAmount / = 25 ;
curChampion - > _maxMana + = skillLevelAfter ;
skillLevelAfter + = ( skillLevelAfter + 1 ) > > 1 ;
2016-09-09 07:32:32 +02:00
curChampion - > _statistics [ kDMStatWisdom ] [ kDMStatMaximum ] + = minorStatIncrease ;
2016-08-26 22:51:17 +02:00
increaseManaFl = true ;
break ;
default :
break ;
}
if ( increaseManaFl ) {
if ( ( curChampion - > _maxMana + = MIN ( _vm - > getRandomNumber ( 4 ) , ( uint16 ) ( newBaseSkillLevel - 1 ) ) ) > 900 )
curChampion - > _maxMana = 900 ;
2016-09-09 07:32:32 +02:00
curChampion - > _statistics [ kDMStatAntimagic ] [ kDMStatMaximum ] + = _vm - > getRandomNumber ( 3 ) ;
2016-08-26 22:51:17 +02:00
}
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 ;
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeStatistics ) ;
2016-08-23 07:54:16 +02:00
drawChampionState ( ( ChampionIndex ) champIndex ) ;
2016-09-25 07:42:35 +02:00
txtMan . printLineFeed ( ) ;
2016-08-18 21:18:08 +02:00
Color curChampionColor = _championColor [ champIndex ] ;
2016-09-25 07:42:35 +02:00
txtMan . printMessage ( curChampionColor , curChampion - > _name ) ;
2016-08-15 20:25:40 +02:00
switch ( _vm - > getGameLanguage ( ) ) { // localized
default :
2016-09-25 07:42:35 +02:00
case Common : : EN_ANY :
txtMan . printMessage ( curChampionColor , " JUST GAINED A " ) ;
break ;
case Common : : DE_DEU :
txtMan . printMessage ( curChampionColor , " HAT SOEBEN STUFE " ) ;
break ;
case Common : : FR_FRA :
txtMan . printMessage ( curChampionColor , " VIENT DE DEVENIR " ) ;
break ;
2016-08-15 20:25:40 +02:00
}
2016-09-25 07:42:35 +02:00
txtMan . printMessage ( curChampionColor , _baseSkillName [ baseSkillIndex ] ) ;
2016-08-15 20:25:40 +02:00
switch ( _vm - > getGameLanguage ( ) ) { // localized
default :
2016-09-25 07:42:35 +02:00
case Common : : EN_ANY :
txtMan . printMessage ( curChampionColor , " ! " ) ;
break ;
case Common : : DE_DEU :
txtMan . printMessage ( curChampionColor , " LEVEL! " ) ;
break ;
case Common : : FR_FRA :
txtMan . printMessage ( curChampionColor , " ERREICHT! " ) ;
break ;
2016-08-15 20:25:40 +02:00
}
2016-08-26 22:51:17 +02:00
}
}
}
2016-08-23 07:54:16 +02:00
int16 ChampionMan : : getDamagedChampionCount ( uint16 attack , int16 wounds , int16 attackType ) {
2016-08-26 22:51:17 +02:00
int16 randomMax = ( attack > > 3 ) + 1 ;
uint16 reducedAttack = attack - randomMax ;
randomMax < < = 1 ;
int16 damagedChampionCount = 0 ;
2016-09-09 07:12:36 +02:00
for ( int16 championIndex = kDMChampionFirst ; championIndex < _partyChampionCount ; championIndex + + ) {
2016-08-26 22:51:17 +02:00
// Actual attack is attack +/- (attack / 8)
2016-08-23 07:54:16 +02:00
if ( addPendingDamageAndWounds_getDamage ( championIndex , MAX ( 1 , reducedAttack + _vm - > getRandomNumber ( randomMax ) ) , wounds , attackType ) )
2016-08-26 22:51:17 +02:00
damagedChampionCount + + ;
}
return damagedChampionCount ;
}
2016-08-23 07:54:16 +02:00
int16 ChampionMan : : getTargetChampionIndex ( int16 mapX , int16 mapY , uint16 cell ) {
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
if ( _partyChampionCount & & ( _vm - > getDistance ( mapX , mapY , dungeon . _partyMapX , dungeon . _partyMapY ) < = 1 ) ) {
2016-08-26 22:51:17 +02:00
signed char orderedCellsToAttack [ 4 ] ;
2016-09-23 07:52:53 +02:00
_vm - > _groupMan - > setOrderedCellsToAttack ( orderedCellsToAttack , dungeon . _partyMapX , dungeon . _partyMapY , mapX , mapY , cell ) ;
2016-08-26 22:51:17 +02:00
for ( uint16 i = 0 ; i < 4 ; i + + ) {
2016-08-23 07:54:16 +02:00
int16 championIndex = getIndexInCell ( orderedCellsToAttack [ i ] ) ;
2016-08-26 22:51:17 +02:00
if ( championIndex > = 0 )
return championIndex ;
}
}
2016-09-09 07:12:36 +02:00
return kDMChampionNone ;
2016-08-26 22:51:17 +02:00
}
2016-08-27 10:54:29 +02:00
int16 ChampionMan : : getDexterity ( Champion * champ ) {
2016-09-09 07:32:32 +02:00
int16 dexterity = _vm - > getRandomNumber ( 8 ) + champ - > _statistics [ kDMStatDexterity ] [ kDMStatCurrent ] ;
2016-08-23 07:54:16 +02:00
dexterity - = ( ( int32 ) ( dexterity > > 1 ) * ( int32 ) champ - > _load ) / getMaximumLoad ( champ ) ;
if ( _partyIsSleeping )
2016-08-26 22:51:17 +02:00
dexterity > > = 1 ;
2016-09-11 11:10:22 +02:00
return CLIP ( 1 + _vm - > getRandomNumber ( 8 ) , dexterity > > 1 , 100 - _vm - > getRandomNumber ( 8 ) ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-27 10:54:29 +02:00
bool ChampionMan : : isLucky ( Champion * champ , uint16 percentage ) {
2016-08-26 22:51:17 +02:00
if ( _vm - > getRandomNumber ( 2 ) & & ( _vm - > getRandomNumber ( 100 ) > percentage ) )
return true ;
2016-09-09 07:32:32 +02:00
unsigned char * curStat = champ - > _statistics [ kDMStatLuck ] ;
2016-09-13 22:07:02 +02:00
bool retVal = ( _vm - > getRandomNumber ( curStat [ kDMStatCurrent ] ) > percentage ) ;
curStat [ kDMStatCurrent ] = CLIP < unsigned char > ( curStat [ kDMStatMinimum ] , curStat [ kDMStatCurrent ] + ( retVal ? - 2 : 2 ) , curStat [ kDMStatMaximum ] ) ;
return retVal ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : championPoison ( int16 champIndex , uint16 attack ) {
2016-09-09 07:12:36 +02:00
if ( ( champIndex = = kDMChampionNone ) | | ( _vm - > indexToOrdinal ( champIndex ) = = _candidateChampionOrdinal ) )
2016-08-26 22:51:17 +02:00
return ;
2016-09-26 21:12:51 +02:00
InventoryMan & inventory = * _vm - > _inventoryMan ;
2016-08-23 07:54:16 +02:00
Champion * curChampion = & _champions [ champIndex ] ;
2016-09-10 14:31:49 +02:00
addPendingDamageAndWounds_getDamage ( champIndex , MAX ( 1 , attack > > 6 ) , kDMWoundNone , kDMAttackTypeNormal ) ;
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeStatistics ) ;
2016-09-26 21:12:51 +02:00
if ( ( _vm - > indexToOrdinal ( champIndex ) = = inventory . _inventoryChampionOrdinal ) & & ( inventory . _panelContent = = kDMPanelContentFoodWaterPoisoned ) )
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributePanel ) ;
2016-08-26 22:51:17 +02:00
if ( - - attack ) {
curChampion - > _poisonEventCount + + ;
TimelineEvent newEvent ;
2016-09-20 21:51:42 +02:00
newEvent . _type = kDMEventTypePoisonChampion ;
2016-08-26 22:51:17 +02:00
newEvent . _priority = champIndex ;
2016-09-19 07:05:37 +02:00
newEvent . _mapTime = _vm - > setMapAndTime ( _vm - > _dungeonMan - > _partyMapIndex , _vm - > _gameTime + 36 ) ;
2016-09-10 21:50:57 +02:00
newEvent . _Bu . _attack = attack ;
2016-08-25 22:38:03 +02:00
_vm - > _timeline - > addEventGetEventIndex ( & newEvent ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
drawChampionState ( ( ChampionIndex ) champIndex ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : setPartyDirection ( int16 dir ) {
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
if ( dir = = dungeon . _partyDir )
2016-08-26 22:51:17 +02:00
return ;
2016-09-23 07:52:53 +02:00
int16 dirDiff = dir - dungeon . _partyDir ;
2016-09-11 09:46:35 +02:00
if ( dirDiff < 0 )
dirDiff + = 4 ;
2016-08-26 22:51:17 +02:00
2016-08-23 07:54:16 +02:00
Champion * curChampion = _champions ;
2016-09-09 07:12:36 +02:00
for ( int16 i = kDMChampionFirst ; i < _partyChampionCount ; i + + ) {
2016-09-11 09:46:35 +02:00
curChampion - > _cell = ( ViewCell ) _vm - > normalizeModulo4 ( curChampion - > _cell + dirDiff ) ;
curChampion - > _dir = ( Direction ) _vm - > normalizeModulo4 ( curChampion - > _dir + dirDiff ) ;
2016-08-26 22:51:17 +02:00
curChampion + + ;
}
2016-09-23 07:52:53 +02:00
dungeon . _partyDir = ( Direction ) dir ;
2016-08-23 07:54:16 +02:00
drawChangedObjectIcons ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : deleteScent ( uint16 scentIndex ) {
uint16 count = - - _party . _scentCount - scentIndex ;
2016-08-26 22:51:17 +02:00
if ( count ) {
for ( uint16 i = 0 ; i < count ; + + i ) {
2016-08-23 07:54:16 +02:00
_party . _scents [ scentIndex + i ] = _party . _scents [ scentIndex + i + 1 ] ;
_party . _scentStrengths [ scentIndex + i ] = _party . _scentStrengths [ scentIndex + i + 1 ] ;
2016-08-26 22:51:17 +02:00
}
}
2016-08-23 07:54:16 +02:00
if ( scentIndex < _party . _firstScentIndex )
_party . _firstScentIndex - - ;
2016-08-26 22:51:17 +02:00
2016-08-23 07:54:16 +02:00
if ( scentIndex < _party . _lastScentIndex )
_party . _lastScentIndex - - ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : addScentStrength ( int16 mapX , int16 mapY , int32 cycleCount ) {
int16 scentIndex = _party . _scentCount ;
2016-08-26 22:51:17 +02:00
if ( scentIndex ) {
2016-09-10 14:53:10 +02:00
bool mergeFl = getFlag ( cycleCount , kDMMaskMergeCycles ) ;
2016-08-26 22:51:17 +02:00
if ( mergeFl )
2016-09-10 14:53:10 +02:00
clearFlag ( cycleCount , kDMMaskMergeCycles ) ;
2016-08-26 22:51:17 +02:00
Scent newScent ; /* BUG0_00 Useless code */
newScent . setMapX ( mapX ) ; /* BUG0_00 Useless code */
newScent . setMapY ( mapY ) ; /* BUG0_00 Useless code */
2016-08-24 08:03:55 +02:00
newScent . setMapIndex ( _vm - > _dungeonMan - > _currMapIndex ) ; /* BUG0_00 Useless code */
2016-08-26 22:51:17 +02:00
2016-08-23 07:54:16 +02:00
Scent * curScent = _party . _scents ; /* BUG0_00 Useless code */
2016-08-26 22:51:17 +02:00
bool cycleCountDefined = false ;
while ( scentIndex - - ) {
if ( & * curScent + + = = & newScent ) {
if ( ! cycleCountDefined ) {
cycleCountDefined = true ;
if ( mergeFl ) {
2016-08-23 07:54:16 +02:00
cycleCount = MAX < int32 > ( _party . _scentStrengths [ scentIndex ] , cycleCount ) ;
2016-08-26 22:51:17 +02:00
} else {
2016-08-23 07:54:16 +02:00
cycleCount = MIN < int32 > ( 80 , _party . _scentStrengths [ scentIndex ] + cycleCount ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-08-23 07:54:16 +02:00
_party . _scentStrengths [ scentIndex ] = cycleCount ;
2016-08-26 22:51:17 +02:00
}
}
}
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : putObjectInLeaderHand ( Thing thing , bool setMousePointer ) {
2017-01-31 18:15:31 +01:00
if ( thing = = _vm - > _thingNone )
2016-08-26 22:51:17 +02:00
return ;
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
2016-08-23 07:54:16 +02:00
_leaderEmptyHanded = false ;
2016-08-25 22:19:34 +02:00
_vm - > _objectMan - > extractIconFromBitmap ( _leaderHandObjectIconIndex = _vm - > _objectMan - > getIconIndex ( _leaderHandObject = thing ) , _vm - > _objectMan - > _objectIconForMousePointer ) ;
2016-09-25 07:42:35 +02:00
evtMan . showMouse ( ) ;
2016-08-25 22:19:34 +02:00
_vm - > _objectMan - > drawLeaderObjectName ( thing ) ;
2016-08-26 22:51:17 +02:00
if ( setMousePointer )
2016-08-23 23:36:18 +02:00
_vm - > _setMousePointerToObjectInMainLoop = true ;
2016-08-26 22:51:17 +02:00
else
2016-09-25 07:42:35 +02:00
evtMan . setPointerToObject ( _vm - > _objectMan - > _objectIconForMousePointer ) ;
2016-08-26 22:51:17 +02:00
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-09-09 07:12:36 +02:00
if ( _leaderIndex ! = kDMChampionNone ) {
2016-08-24 08:03:55 +02:00
_champions [ _leaderIndex ] . _load + = _vm - > _dungeonMan - > getObjectWeight ( thing ) ;
2016-09-09 07:32:32 +02:00
setFlag ( _champions [ _leaderIndex ] . _attributes , kDMAttributeLoad ) ;
2016-08-23 07:54:16 +02:00
drawChampionState ( _leaderIndex ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-08-23 07:54:16 +02:00
int16 ChampionMan : : getMovementTicks ( Champion * champ ) {
uint16 maximumLoad = getMaximumLoad ( champ ) ;
2016-08-26 22:51:17 +02:00
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 ;
}
2016-09-09 07:32:32 +02:00
if ( getFlag ( champ - > _wounds , kDMWoundFeet ) )
2016-08-26 22:51:17 +02:00
ticks + = woundTicks ;
2016-09-10 11:47:36 +02:00
if ( _vm - > _objectMan - > getIconIndex ( champ - > _slots [ kDMSlotFeet ] ) = = kDMIconIndiceArmourBootOfSpeed )
2016-08-26 22:51:17 +02:00
ticks - - ;
return ticks ;
}
2016-08-23 07:54:16 +02:00
bool ChampionMan : : isAmmunitionCompatibleWithWeapon ( uint16 champIndex , uint16 weaponSlotIndex , uint16 ammunitionSlotIndex ) {
Champion * curChampion = & _champions [ champIndex ] ;
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-08-26 22:51:17 +02:00
Thing curThing = curChampion - > _slots [ weaponSlotIndex ] ;
2016-09-23 07:52:53 +02:00
2016-09-11 00:33:54 +02:00
if ( curThing . getType ( ) ! = kDMThingTypeWeapon )
2016-08-26 22:51:17 +02:00
return false ;
2016-09-23 07:52:53 +02:00
WeaponInfo * weaponInfo = dungeon . getWeaponInfo ( curThing ) ;
2016-09-11 23:06:29 +02:00
int16 weaponClass = kDMWeaponClassNone ;
2016-08-26 22:51:17 +02:00
2016-09-11 23:06:29 +02:00
if ( ( weaponInfo - > _class > = kDMWeaponClassFirstBow ) & & ( weaponInfo - > _class < = kDMWeaponClassLastBow ) )
weaponClass = kDMWeaponClassBowAmmunition ;
else if ( ( weaponInfo - > _class > = kDMWeaponClassFirstSling ) & & ( weaponInfo - > _class < = kDMWeaponClassLastSling ) )
weaponClass = kDMWeaponClassSlingAmmunition ;
2016-08-26 22:51:17 +02:00
2016-09-11 23:06:29 +02:00
if ( weaponClass = = kDMWeaponClassNone )
2016-08-26 22:51:17 +02:00
return false ;
curThing = curChampion - > _slots [ ammunitionSlotIndex ] ;
2016-09-23 07:52:53 +02:00
weaponInfo = dungeon . getWeaponInfo ( curThing ) ;
2016-09-11 00:33:54 +02:00
return ( ( curThing . getType ( ) = = kDMThingTypeWeapon ) & & ( weaponInfo - > _class = = weaponClass ) ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : drawAllChampionStates ( ) {
2016-09-09 07:12:36 +02:00
for ( int16 i = kDMChampionFirst ; i < _partyChampionCount ; i + + )
2016-08-23 07:54:16 +02:00
drawChampionState ( ( ChampionIndex ) i ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : viAltarRebirth ( uint16 champIndex ) {
Champion * curChampion = & _champions [ champIndex ] ;
2016-09-09 07:12:36 +02:00
if ( getIndexInCell ( curChampion - > _cell ) ! = kDMChampionNone ) {
2016-09-11 00:33:54 +02:00
uint16 numCell = kDMCellNorthWest ;
2016-09-09 07:12:36 +02:00
while ( getIndexInCell ( numCell ) ! = kDMChampionNone )
2016-08-26 22:51:17 +02:00
numCell + + ;
curChampion - > _cell = ( ViewCell ) numCell ;
}
uint16 maximumHealth = curChampion - > _maxHealth ;
curChampion - > _maxHealth = MAX ( 25 , maximumHealth - ( maximumHealth > > 6 ) - 1 ) ;
curChampion - > _currHealth = curChampion - > _maxHealth > > 1 ;
2016-08-25 21:59:02 +02:00
_vm - > _menuMan - > drawSpellAreaControls ( _magicCasterChampionIndex ) ;
2016-08-24 08:03:55 +02:00
curChampion - > _dir = _vm - > _dungeonMan - > _partyDir ;
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeActionHand | kDMAttributeStatusBox | kDMAttributeIcon ) ;
2016-08-23 07:54:16 +02:00
drawChampionState ( ( ChampionIndex ) champIndex ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : clickOnSlotBox ( uint16 slotBoxIndex ) {
2016-08-26 22:51:17 +02:00
uint16 champIndex ;
uint16 slotIndex ;
2016-09-26 21:12:51 +02:00
InventoryMan & inventory = * _vm - > _inventoryMan ;
2016-09-18 22:15:51 +02:00
if ( slotBoxIndex < kDMSlotBoxInventoryFirstSlot ) {
2016-08-23 07:54:16 +02:00
if ( _candidateChampionOrdinal )
2016-08-26 22:51:17 +02:00
return ;
champIndex = slotBoxIndex > > 1 ;
2016-09-26 21:12:51 +02:00
if ( ( champIndex > = _partyChampionCount ) | | ( _vm - > indexToOrdinal ( champIndex ) = = inventory . _inventoryChampionOrdinal ) | | ! _champions [ champIndex ] . _currHealth )
2016-08-26 22:51:17 +02:00
return ;
2016-08-23 07:54:16 +02:00
slotIndex = getHandSlotIndex ( slotBoxIndex ) ;
2016-08-26 22:51:17 +02:00
} else {
2016-09-26 21:12:51 +02:00
champIndex = _vm - > ordinalToIndex ( inventory . _inventoryChampionOrdinal ) ;
2016-09-18 22:15:51 +02:00
slotIndex = slotBoxIndex - kDMSlotBoxInventoryFirstSlot ;
2016-08-26 22:51:17 +02:00
}
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-08-23 07:54:16 +02:00
Thing leaderHandObject = _leaderHandObject ;
2016-08-26 22:51:17 +02:00
Thing slotThing ;
2016-09-23 07:52:53 +02:00
if ( slotIndex > = kDMSlotChest1 )
2016-09-26 21:12:51 +02:00
slotThing = inventory . _chestSlots [ slotIndex - kDMSlotChest1 ] ;
2016-09-23 07:52:53 +02:00
else
2016-08-23 07:54:16 +02:00
slotThing = _champions [ champIndex ] . _slots [ slotIndex ] ;
2016-08-26 22:51:17 +02:00
2017-01-31 18:15:31 +01:00
if ( ( slotThing = = _vm - > _thingNone ) & & ( leaderHandObject = = _vm - > _thingNone ) )
2016-08-26 22:51:17 +02:00
return ;
2017-01-31 18:15:31 +01:00
if ( ( leaderHandObject ! = _vm - > _thingNone ) & & ( ! ( dungeon . _objectInfos [ dungeon . getObjectInfoIndex ( leaderHandObject ) ] . _allowedSlots & _slotMasks [ slotIndex ] ) ) )
2016-08-26 22:51:17 +02:00
return ;
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
evtMan . showMouse ( ) ;
2017-01-31 18:15:31 +01:00
if ( leaderHandObject ! = _vm - > _thingNone )
2016-08-23 07:54:16 +02:00
getObjectRemovedFromLeaderHand ( ) ;
2016-08-26 22:51:17 +02:00
2017-01-31 18:15:31 +01:00
if ( slotThing ! = _vm - > _thingNone ) {
2016-08-23 07:54:16 +02:00
getObjectRemovedFromSlot ( champIndex , slotIndex ) ;
putObjectInLeaderHand ( slotThing , false ) ;
2016-08-26 22:51:17 +02:00
}
2017-01-31 18:15:31 +01:00
if ( leaderHandObject ! = _vm - > _thingNone )
2016-08-23 07:54:16 +02:00
addObjectInSlot ( ( ChampionIndex ) champIndex , leaderHandObject , ( ChampionSlot ) slotIndex ) ;
2016-08-26 22:51:17 +02:00
2016-08-23 07:54:16 +02:00
drawChampionState ( ( ChampionIndex ) champIndex ) ;
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
bool ChampionMan : : isProjectileSpellCast ( uint16 champIndex , Thing thing , int16 kineticEnergy , uint16 requiredManaAmount ) {
Champion * curChampion = & _champions [ champIndex ] ;
2016-08-26 22:51:17 +02:00
if ( curChampion - > _currMana < requiredManaAmount )
return false ;
curChampion - > _currMana - = requiredManaAmount ;
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeStatistics ) ;
2016-08-26 22:51:17 +02:00
int16 stepEnergy = 10 - MIN ( 8 , curChampion - > _maxMana > > 3 ) ;
if ( kineticEnergy < ( stepEnergy < < 2 ) ) {
kineticEnergy + = 3 ;
stepEnergy - - ;
}
2016-08-23 07:54:16 +02:00
championShootProjectile ( curChampion , thing , kineticEnergy , 90 , stepEnergy ) ;
2016-08-26 22:51:17 +02:00
return true ; // fix BUG_01
}
2016-08-27 10:54:29 +02:00
void ChampionMan : : championShootProjectile ( Champion * champ , Thing thing , int16 kineticEnergy , int16 attack , int16 stepEnergy ) {
2016-08-26 22:51:17 +02:00
Direction newDirection = champ - > _dir ;
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
_vm - > _projexpl - > createProjectile ( thing , dungeon . _partyMapX , dungeon . _partyMapY , _vm - > normalizeModulo4 ( ( ( ( champ - > _cell - newDirection + 1 ) & 0x0002 ) > > 1 ) + newDirection ) , newDirection , kineticEnergy , attack , stepEnergy ) ;
2016-08-23 23:36:18 +02:00
_vm - > _projectileDisableMovementTicks = 4 ;
_vm - > _lastProjectileDisabledMovementDirection = newDirection ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : applyAndDrawPendingDamageAndWounds ( ) {
Champion * championPtr = _champions ;
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
TextMan & txtMan = * _vm - > _textMan ;
2016-09-25 22:33:40 +02:00
DisplayMan & display = * _vm - > _displayMan ;
2016-09-25 07:42:35 +02:00
2016-09-09 07:12:36 +02:00
for ( uint16 championIndex = kDMChampionFirst ; championIndex < _partyChampionCount ; championIndex + + , championPtr + + ) {
2016-08-23 07:54:16 +02:00
int16 pendingWounds = _championPendingWounds [ championIndex ] ;
2016-08-26 22:51:17 +02:00
setFlag ( championPtr - > _wounds , pendingWounds ) ;
2016-08-23 07:54:16 +02:00
_championPendingWounds [ championIndex ] = 0 ;
uint16 pendingDamage = _championPendingDamage [ championIndex ] ;
2016-08-26 22:51:17 +02:00
if ( ! pendingDamage )
continue ;
2016-08-23 07:54:16 +02:00
_championPendingDamage [ championIndex ] = 0 ;
2016-08-26 22:51:17 +02:00
int16 curHealth = championPtr - > _currHealth ;
if ( ! curHealth )
continue ;
// DEBUG CODE
if ( _vm - > _console - > _debugGodmodeHP = = false )
curHealth - = pendingDamage ;
2016-09-23 07:52:53 +02:00
if ( curHealth < = 0 )
2016-08-23 07:54:16 +02:00
championKill ( championIndex ) ;
2016-09-23 07:52:53 +02:00
else {
2016-08-26 22:51:17 +02:00
championPtr - > _currHealth = curHealth ;
2016-09-09 07:32:32 +02:00
setFlag ( championPtr - > _attributes , kDMAttributeStatistics ) ;
2016-09-23 07:52:53 +02:00
if ( pendingWounds )
2016-09-09 07:32:32 +02:00
setFlag ( championPtr - > _attributes , kDMAttributeWounds ) ;
2016-08-26 22:51:17 +02:00
2016-09-18 11:46:53 +02:00
int16 textPosX = championIndex * kDMChampionStatusBoxSpacing ;
2016-08-26 22:51:17 +02:00
int16 textPosY ;
Box blitBox ;
2016-09-16 21:17:02 +02:00
blitBox . _rect . top = 0 ;
2016-09-25 07:42:35 +02:00
evtMan . showMouse ( ) ;
2016-08-26 22:51:17 +02:00
2016-08-25 21:25:18 +02:00
if ( _vm - > indexToOrdinal ( championIndex ) = = _vm - > _inventoryMan - > _inventoryChampionOrdinal ) {
2016-09-16 21:17:02 +02:00
blitBox . _rect . bottom = 28 ;
blitBox . _rect . left = textPosX + 7 ;
blitBox . _rect . right = blitBox . _rect . left + 31 ; /* Box is over the champion portrait in the status box */
2016-09-25 22:33:40 +02:00
display . blitToScreen ( display . getNativeBitmapOrGraphic ( kDMGraphicIdxDamageToChampionBig ) , & blitBox , k16_byteWidth , kDMColorFlesh , 29 ) ;
2016-08-26 22:51:17 +02:00
// 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 {
2016-09-16 21:17:02 +02:00
blitBox . _rect . bottom = 6 ;
blitBox . _rect . left = textPosX ;
blitBox . _rect . right = blitBox . _rect . left + 47 ; /* Box is over the champion name in the status box */
2016-09-25 22:33:40 +02:00
display . blitToScreen ( display . getNativeBitmapOrGraphic ( kDMGraphicIdxDamageToChampionSmall ) , & blitBox , k24_byteWidth , kDMColorFlesh , 7 ) ;
2016-08-26 22:51:17 +02:00
// 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 ;
}
2016-09-25 07:42:35 +02:00
txtMan . printToLogicalScreen ( textPosX , textPosY , kDMColorWhite , kDMColorRed , getStringFromInteger ( pendingDamage , false , 3 ) . c_str ( ) ) ;
2016-08-26 22:51:17 +02:00
int16 eventIndex = championPtr - > _hideDamageReceivedIndex ;
if ( eventIndex = = - 1 ) {
TimelineEvent newEvent ;
2016-09-20 21:51:42 +02:00
newEvent . _type = kDMEventTypeHideDamageReceived ;
2016-09-19 07:05:37 +02:00
newEvent . _mapTime = _vm - > setMapAndTime ( _vm - > _dungeonMan - > _partyMapIndex , _vm - > _gameTime + 5 ) ;
2016-08-26 22:51:17 +02:00
newEvent . _priority = championIndex ;
2016-08-25 22:38:03 +02:00
championPtr - > _hideDamageReceivedIndex = _vm - > _timeline - > addEventGetEventIndex ( & newEvent ) ;
2016-08-26 22:51:17 +02:00
} else {
2016-08-25 22:38:03 +02:00
TimelineEvent * curEvent = & _vm - > _timeline - > _events [ eventIndex ] ;
2016-09-19 07:05:37 +02:00
curEvent - > _mapTime = _vm - > setMapAndTime ( _vm - > _dungeonMan - > _partyMapIndex , _vm - > _gameTime + 5 ) ;
2016-08-25 22:38:03 +02:00
_vm - > _timeline - > fixChronology ( _vm - > _timeline - > getIndex ( eventIndex ) ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
drawChampionState ( ( ChampionIndex ) championIndex ) ;
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
}
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : championKill ( uint16 champIndex ) {
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-08-23 07:54:16 +02:00
Champion * curChampion = & _champions [ champIndex ] ;
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
2016-09-25 22:33:40 +02:00
DisplayMan & display = * _vm - > _displayMan ;
2016-09-26 21:12:51 +02:00
InventoryMan & inventory = * _vm - > _inventoryMan ;
2016-08-26 22:51:17 +02:00
curChampion - > _currHealth = 0 ;
2016-09-09 07:32:32 +02:00
setFlag ( curChampion - > _attributes , kDMAttributeStatusBox ) ;
2016-09-26 21:12:51 +02:00
if ( _vm - > indexToOrdinal ( champIndex ) = = inventory . _inventoryChampionOrdinal ) {
2016-08-23 23:36:18 +02:00
if ( _vm - > _pressingEye ) {
_vm - > _pressingEye = false ;
2016-09-25 07:42:35 +02:00
evtMan . _ignoreMouseMovements = false ;
2016-08-23 07:54:16 +02:00
if ( ! _leaderEmptyHanded ) {
2016-08-25 22:19:34 +02:00
_vm - > _objectMan - > drawLeaderObjectName ( _leaderHandObject ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-25 07:42:35 +02:00
evtMan . _hideMousePointerRequestCount = 1 ;
evtMan . hideMouse ( ) ;
2016-08-23 23:36:18 +02:00
} else if ( _vm - > _pressingMouth ) {
_vm - > _pressingMouth = false ;
2016-09-25 07:42:35 +02:00
evtMan . _ignoreMouseMovements = false ;
evtMan . _hideMousePointerRequestCount = 1 ;
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-26 21:12:51 +02:00
inventory . toggleInventory ( kDMChampionCloseInventory ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
dropAllObjects ( champIndex ) ;
2016-09-23 07:52:53 +02:00
Thing unusedThing = dungeon . getUnusedThing ( kDMMaskChampionBones | kDMThingTypeJunk ) ;
2016-08-26 22:51:17 +02:00
uint16 curCell = 0 ;
2017-01-31 18:15:31 +01:00
if ( unusedThing ! = _vm - > _thingNone ) {
2016-09-23 07:52:53 +02:00
Junk * L0966_ps_Junk = ( Junk * ) dungeon . getThingData ( unusedThing ) ;
2016-09-12 22:20:31 +02:00
L0966_ps_Junk - > setType ( kDMJunkTypeBones ) ;
2016-08-26 22:51:17 +02:00
L0966_ps_Junk - > setDoNotDiscard ( true ) ;
L0966_ps_Junk - > setChargeCount ( champIndex ) ;
curCell = curChampion - > _cell ;
2016-09-23 07:52:53 +02:00
_vm - > _moveSens - > getMoveResult ( _vm - > thingWithNewCell ( unusedThing , curCell ) , kDMMapXNotOnASquare , 0 , dungeon . _partyMapX , dungeon . _partyMapY ) ;
2016-08-26 22:51:17 +02:00
}
curChampion - > _symbolStep = 0 ;
curChampion - > _symbols [ 0 ] = ' \0 ' ;
2016-09-23 07:52:53 +02:00
curChampion - > _dir = dungeon . _partyDir ;
2016-08-26 22:51:17 +02:00
curChampion - > _maximumDamageReceived = 0 ;
2016-09-23 07:52:53 +02:00
uint16 curChampionIconIndex = getChampionIconIndex ( curCell , dungeon . _partyDir ) ;
2016-09-25 07:42:35 +02:00
if ( _vm - > indexToOrdinal ( curChampionIconIndex ) = = evtMan . _useChampionIconOrdinalAsMousePointerBitmap ) {
evtMan . _mousePointerBitmapUpdated = true ;
evtMan . _useChampionIconOrdinalAsMousePointerBitmap = _vm - > indexToOrdinal ( kDMChampionNone ) ;
2016-08-26 22:51:17 +02:00
}
if ( curChampion - > _poisonEventCount )
2016-08-23 07:54:16 +02:00
unpoison ( champIndex ) ;
2016-08-26 22:51:17 +02:00
2016-09-25 22:33:40 +02:00
display . _useByteBoxCoordinates = false ;
display . fillScreenBox ( _boxChampionIcons [ curChampionIconIndex ] , kDMColorBlack ) ;
2016-08-23 07:54:16 +02:00
drawChampionState ( ( ChampionIndex ) champIndex ) ;
2016-08-26 22:51:17 +02:00
2016-09-04 08:47:13 +02:00
ChampionIndex aliveChampionIndex ;
int idx = 0 ;
for ( curChampion = _champions ; ( idx < _partyChampionCount ) & & ( curChampion - > _currHealth = = 0 ) ; idx + + , curChampion + + )
;
2016-08-26 22:51:17 +02:00
2016-09-04 08:47:13 +02:00
aliveChampionIndex = ( ChampionIndex ) idx ;
2016-08-23 07:54:16 +02:00
if ( aliveChampionIndex = = _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) */
_partyDead = true ;
2016-08-26 22:51:17 +02:00
return ;
}
2016-08-23 07:54:16 +02:00
if ( champIndex = = _leaderIndex )
2016-09-25 07:42:35 +02:00
evtMan . commandSetLeader ( aliveChampionIndex ) ;
2016-08-26 22:51:17 +02:00
2016-08-23 07:54:16 +02:00
if ( champIndex = = _magicCasterChampionIndex )
2016-08-25 21:59:02 +02:00
_vm - > _menuMan - > setMagicCasterAndDrawSpellArea ( aliveChampionIndex ) ;
2016-08-26 22:51:17 +02:00
else
2016-08-25 21:59:02 +02:00
_vm - > _menuMan - > drawSpellAreaControls ( _magicCasterChampionIndex ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : dropAllObjects ( uint16 champIndex ) {
2016-08-26 22:51:17 +02:00
static const int16 slotDropOrder [ 30 ] = {
2016-09-10 11:47:36 +02:00
kDMSlotFeet ,
kDMSlotLegs ,
kDMSlotQuiverLine2_2 ,
kDMSlotQuiverLine1_2 ,
kDMSlotQuiverLine2_1 ,
kDMSlotQuiverLine1_1 ,
kDMSlotPouch_2 ,
kDMSlotPouch1 ,
kDMSlotTorso ,
kDMSlotBackpackLine1_1 ,
kDMSlotBackpackLine2_2 ,
kDMSlotBackpackLine2_3 ,
kDMSlotBackpackLine2_4 ,
kDMSlotBackpackLine2_5 ,
kDMSlotBackpackLine2_6 ,
kDMSlotBackpackLine2_7 ,
kDMSlotBackpackLine2_8 ,
kDMSlotBackpackLine2_9 ,
kDMSlotBackpackLine1_2 ,
kDMSlotBackpackLine1_3 ,
kDMSlotBackpackLine1_4 ,
kDMSlotBackpackLine1_5 ,
kDMSlotBackpackLine1_6 ,
kDMSlotBackpackLine1_7 ,
kDMSlotBackpackLine1_8 ,
kDMSlotBackpackLine1_9 ,
kDMSlotNeck ,
kDMSlotHead ,
kDMSlotReadyHand ,
kDMSlotActionHand
2016-08-26 22:51:17 +02:00
} ;
2016-08-23 07:54:16 +02:00
uint16 curCell = _champions [ champIndex ] . _cell ;
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-09-10 11:47:36 +02:00
for ( uint16 slotIndex = kDMSlotReadyHand ; slotIndex < kDMSlotChest1 ; slotIndex + + ) {
2016-08-23 07:54:16 +02:00
Thing curThing = getObjectRemovedFromSlot ( champIndex , slotDropOrder [ slotIndex ] ) ;
2017-01-31 18:15:31 +01:00
if ( curThing ! = _vm - > _thingNone )
2016-09-23 07:52:53 +02:00
_vm - > _moveSens - > getMoveResult ( _vm - > thingWithNewCell ( curThing , curCell ) , kDMMapXNotOnASquare , 0 , dungeon . _partyMapX , dungeon . _partyMapY ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : unpoison ( int16 champIndex ) {
2016-09-09 07:12:36 +02:00
if ( champIndex = = kDMChampionNone )
2016-08-26 22:51:17 +02:00
return ;
2016-08-25 22:38:03 +02:00
TimelineEvent * eventPtr = _vm - > _timeline - > _events ;
for ( uint16 eventIndex = 0 ; eventIndex < _vm - > _timeline - > _eventMaxCount ; eventPtr + + , eventIndex + + ) {
2016-09-20 21:51:42 +02:00
if ( ( eventPtr - > _type = = kDMEventTypePoisonChampion ) & & ( eventPtr - > _priority = = champIndex ) )
2016-08-25 22:38:03 +02:00
_vm - > _timeline - > deleteEvent ( eventIndex ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
_champions [ champIndex ] . _poisonEventCount = 0 ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : applyTimeEffects ( ) {
if ( ! _partyChampionCount )
2016-08-26 22:51:17 +02:00
return ;
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-09-26 21:12:51 +02:00
InventoryMan & inventory = * _vm - > _inventoryMan ;
2016-08-26 22:51:17 +02:00
Scent checkScent ;
2016-09-23 07:52:53 +02:00
checkScent . setMapX ( dungeon . _partyMapX ) ;
checkScent . setMapY ( dungeon . _partyMapY ) ;
checkScent . setMapIndex ( dungeon . _partyMapIndex ) ;
2016-08-26 22:51:17 +02:00
2016-08-23 07:54:16 +02:00
for ( byte loopScentIndex = 0 ; loopScentIndex + 1 < _party . _scentCount ; loopScentIndex + + ) {
if ( & _party . _scents [ loopScentIndex ] ! = & checkScent ) {
_party . _scentStrengths [ loopScentIndex ] = MAX ( 0 , _party . _scentStrengths [ loopScentIndex ] - 1 ) ;
if ( ! _party . _scentStrengths [ loopScentIndex ] & & ! loopScentIndex ) {
deleteScent ( 0 ) ;
2016-08-26 22:51:17 +02:00
continue ;
}
}
}
2016-08-23 23:36:18 +02:00
uint16 gameTime = _vm - > _gameTime & 0xFFFF ;
2016-08-26 22:51:17 +02:00
uint16 timeCriteria = ( ( ( gameTime & 0x0080 ) + ( ( gameTime & 0x0100 ) > > 2 ) ) + ( ( gameTime & 0x0040 ) < < 2 ) ) > > 2 ;
2016-08-23 07:54:16 +02:00
Champion * championPtr = _champions ;
2016-09-09 07:12:36 +02:00
for ( uint16 championIndex = kDMChampionFirst ; championIndex < _partyChampionCount ; championIndex + + , championPtr + + ) {
2016-08-23 23:36:18 +02:00
if ( championPtr - > _currHealth & & ( _vm - > indexToOrdinal ( championIndex ) ! = _candidateChampionOrdinal ) ) {
2016-09-09 07:32:32 +02:00
uint16 wizardSkillLevel = getSkillLevel ( championIndex , kDMSkillWizard ) + getSkillLevel ( championIndex , kDMSkillPriest ) ;
2016-08-26 22:51:17 +02:00
if ( ( championPtr - > _currMana < championPtr - > _maxMana )
2016-09-09 07:32:32 +02:00
& & ( timeCriteria < championPtr - > _statistics [ kDMStatWisdom ] [ kDMStatCurrent ] + wizardSkillLevel ) ) {
2016-08-26 22:51:17 +02:00
int16 manaGain = championPtr - > _maxMana / 40 ;
2016-08-23 07:54:16 +02:00
if ( _partyIsSleeping )
2016-08-26 22:51:17 +02:00
manaGain < < = 1 ;
manaGain + + ;
2016-08-23 07:54:16 +02:00
decrementStamina ( championIndex , manaGain * MAX ( 7 , 16 - wizardSkillLevel ) ) ;
2016-08-26 22:51:17 +02:00
championPtr - > _currMana + = MIN < int16 > ( manaGain , championPtr - > _maxMana - championPtr - > _currMana ) ;
} else if ( championPtr - > _currMana > championPtr - > _maxMana )
championPtr - > _currMana - - ;
2016-09-09 07:32:32 +02:00
for ( int16 idx = kDMSkillWater ; idx > = kDMSkillFighter ; idx - - ) {
2016-08-26 22:51:17 +02:00
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 ;
2016-09-11 11:10:22 +02:00
int16 staminaAmount = CLIP ( 1 , ( championPtr - > _maxStamina > > 8 ) - 1 , 6 ) ;
2016-08-23 07:54:16 +02:00
if ( _partyIsSleeping )
2016-08-26 22:51:17 +02:00
staminaAmount < < = 1 ;
2016-08-25 22:19:34 +02:00
int32 compDelay = _vm - > _gameTime - _vm - > _projexpl - > _lastPartyMovementTime ;
2016-08-26 22:51:17 +02:00
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 ) ) ;
2016-08-23 07:54:16 +02:00
decrementStamina ( championIndex , staminaLoss ) ;
2016-08-26 22:51:17 +02:00
if ( championPtr - > _food < - 1024 )
championPtr - > _food = - 1024 ;
if ( championPtr - > _water < - 1024 )
championPtr - > _water = - 1024 ;
2016-09-09 07:32:32 +02:00
if ( ( championPtr - > _currHealth < championPtr - > _maxHealth ) & & ( championPtr - > _currStamina > = ( championPtr - > _maxStamina > > 2 ) ) & & ( timeCriteria < ( championPtr - > _statistics [ kDMStatVitality ] [ kDMStatCurrent ] + 12 ) ) ) {
2016-08-26 22:51:17 +02:00
int16 healthGain = ( championPtr - > _maxHealth > > 7 ) + 1 ;
2016-08-23 07:54:16 +02:00
if ( _partyIsSleeping )
2016-08-26 22:51:17 +02:00
healthGain < < = 1 ;
2016-09-10 11:47:36 +02:00
if ( _vm - > _objectMan - > getIconIndex ( championPtr - > _slots [ kDMSlotNeck ] ) = = kDMIconIndiceJunkEkkhardCross )
2016-08-26 22:51:17 +02:00
healthGain + = ( healthGain > > 1 ) + 1 ;
championPtr - > _currHealth + = MIN ( healthGain , ( int16 ) ( championPtr - > _maxHealth - championPtr - > _currHealth ) ) ;
}
2016-08-23 23:36:18 +02:00
if ( ! ( ( int ) _vm - > _gameTime & ( _partyIsSleeping ? 63 : 255 ) ) ) {
2016-09-09 07:32:32 +02:00
for ( uint16 i = kDMStatLuck ; i < = kDMStatAntifire ; i + + ) {
2016-08-26 22:51:17 +02:00
byte * curStatistic = championPtr - > _statistics [ i ] ;
2016-09-09 07:32:32 +02:00
uint16 statisticMaximum = curStatistic [ kDMStatMaximum ] ;
if ( curStatistic [ kDMStatCurrent ] < statisticMaximum )
curStatistic [ kDMStatCurrent ] + + ;
else if ( curStatistic [ kDMStatCurrent ] > statisticMaximum )
curStatistic [ kDMStatCurrent ] - = curStatistic [ kDMStatCurrent ] / statisticMaximum ;
2016-08-26 22:51:17 +02:00
}
}
2016-09-23 07:52:53 +02:00
if ( ! _partyIsSleeping & & ( championPtr - > _dir ! = dungeon . _partyDir ) & & ( _vm - > _projexpl - > _lastCreatureAttackTime + 60 < _vm - > _gameTime ) ) {
championPtr - > _dir = dungeon . _partyDir ;
2016-08-26 22:51:17 +02:00
championPtr - > _maximumDamageReceived = 0 ;
2016-09-09 07:32:32 +02:00
setFlag ( championPtr - > _attributes , kDMAttributeIcon ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-09 07:32:32 +02:00
setFlag ( championPtr - > _attributes , kDMAttributeStatistics ) ;
2016-09-26 21:12:51 +02:00
if ( _vm - > indexToOrdinal ( championIndex ) = = inventory . _inventoryChampionOrdinal ) {
if ( _vm - > _pressingMouth | | _vm - > _pressingEye | | ( inventory . _panelContent = = kDMPanelContentFoodWaterPoisoned ) ) {
2016-09-09 07:32:32 +02:00
setFlag ( championPtr - > _attributes , kDMAttributePanel ) ;
2016-08-26 22:51:17 +02:00
}
}
}
}
2016-08-23 07:54:16 +02:00
drawAllChampionStates ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-27 10:54:29 +02:00
void ChampionMan : : savePartyPart2 ( Common : : OutSaveFile * file ) {
2016-08-26 22:51:17 +02:00
for ( uint16 i = 0 ; i < 4 ; + + i ) {
2016-08-23 07:54:16 +02:00
Champion * champ = & _champions [ i ] ;
2016-08-26 22:51:17 +02:00
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 ] ) ;
}
2016-08-23 07:54:16 +02:00
Party & party = _party ;
2016-08-26 22:51:17 +02:00
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 ) ;
}
2016-08-27 10:54:29 +02:00
void ChampionMan : : loadPartyPart2 ( Common : : InSaveFile * file ) {
2016-08-26 22:51:17 +02:00
for ( uint16 i = 0 ; i < 4 ; + + i ) {
2016-08-23 07:54:16 +02:00
Champion * champ = & _champions [ i ] ;
2016-08-26 22:51:17 +02:00
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 ( ) ;
}
2016-08-23 07:54:16 +02:00
Party & party = _party ;
2016-08-26 22:51:17 +02:00
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 ( ) ;
}
2016-08-23 07:54:16 +02:00
ChampionIndex ChampionMan : : getIndexInCell ( int16 cell ) {
for ( uint16 i = 0 ; i < _partyChampionCount ; + + i ) {
if ( ( _champions [ i ] . _cell = = cell ) & & _champions [ i ] . _currHealth )
2016-08-26 22:51:17 +02:00
return ( ChampionIndex ) i ;
}
2016-09-09 07:12:36 +02:00
return kDMChampionNone ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : resetDataToStartGame ( ) {
2016-09-19 21:45:14 +02:00
if ( _vm - > _gameMode = = kDMModeLoadSavedGame ) {
2016-09-04 08:47:13 +02:00
Thing handThing = _leaderHandObject ;
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
2017-01-31 18:15:31 +01:00
if ( handThing = = _vm - > _thingNone ) {
2016-08-23 07:54:16 +02:00
_leaderEmptyHanded = true ;
2016-09-09 07:12:36 +02:00
_leaderHandObjectIconIndex = kDMIconIndiceNone ;
2016-09-25 07:42:35 +02:00
evtMan . setMousePointer ( ) ;
2016-09-04 08:47:13 +02:00
} else
putObjectInLeaderHand ( handThing , true ) ; /* This call will add the weight of the leader hand object to the Load of the leader a first time */
Champion * curChampion = _champions ;
for ( int16 idx = 0 ; idx < _partyChampionCount ; idx + + , curChampion + + ) {
2016-09-09 07:32:32 +02:00
clearFlag ( curChampion - > _attributes , kDMAttributeNameTitle | kDMAttributeStatistics | kDMAttributeLoad | kDMAttributeIcon | kDMAttributePanel | kDMAttributeStatusBox | kDMAttributeWounds | kDMAttributeViewport | kDMAttributeActionHand ) ;
setFlag ( curChampion - > _attributes , kDMAttributeActionHand | kDMAttributeStatusBox | kDMAttributeIcon ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
drawAllChampionStates ( ) ;
2016-09-04 08:47:13 +02:00
ChampionIndex championIndex = _leaderIndex ;
2016-09-09 07:12:36 +02:00
if ( championIndex ! = kDMChampionNone ) {
_leaderIndex = kDMChampionNone ;
2016-09-25 07:42:35 +02:00
evtMan . commandSetLeader ( championIndex ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-04 08:47:13 +02:00
championIndex = _magicCasterChampionIndex ;
2016-09-09 07:12:36 +02:00
if ( championIndex ! = kDMChampionNone ) {
_magicCasterChampionIndex = kDMChampionNone ;
2016-09-04 08:47:13 +02:00
_vm - > _menuMan - > setMagicCasterAndDrawSpellArea ( championIndex ) ;
2016-08-26 22:51:17 +02:00
}
return ;
}
2017-01-31 18:15:31 +01:00
_leaderHandObject = _vm - > _thingNone ;
2016-09-09 07:12:36 +02:00
_leaderHandObjectIconIndex = kDMIconIndiceNone ;
2016-08-23 07:54:16 +02:00
_leaderEmptyHanded = true ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : addCandidateChampionToParty ( uint16 championPortraitIndex ) {
if ( ! _leaderEmptyHanded )
2016-08-26 22:51:17 +02:00
return ;
2016-08-23 07:54:16 +02:00
if ( _partyChampionCount = = 4 )
2016-08-26 22:51:17 +02:00
return ;
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
2016-09-25 22:33:40 +02:00
DisplayMan & display = * _vm - > _displayMan ;
2016-08-23 07:54:16 +02:00
uint16 previousPartyChampionCount = _partyChampionCount ;
Champion * championPtr = & _champions [ previousPartyChampionCount ] ;
2016-08-26 22:51:17 +02:00
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)
2016-09-25 22:33:40 +02:00
display . _useByteBoxCoordinates = true ;
display . blitToBitmap ( display . getNativeBitmapOrGraphic ( kDMGraphicIdxChampionPortraits ) , championPtr - > _portrait , _boxChampionPortrait , getChampionPortraitX ( championPortraitIndex ) , getChampionPortraitY ( championPortraitIndex ) , k128_byteWidth , k16_byteWidth , kDMColorNoTransparency , 87 , 29 ) ;
2016-09-10 14:31:49 +02:00
championPtr - > _actionIndex = kDMActionNone ;
2016-08-26 22:51:17 +02:00
championPtr - > _enableActionEventIndex = - 1 ;
championPtr - > _hideDamageReceivedIndex = - 1 ;
2016-09-23 07:52:53 +02:00
championPtr - > _dir = dungeon . _partyDir ;
2016-09-16 07:46:10 +02:00
uint16 viewCell = kDMViewCellFronLeft ;
2016-09-23 07:52:53 +02:00
while ( getIndexInCell ( _vm - > normalizeModulo4 ( viewCell + dungeon . _partyDir ) ) ! = kDMChampionNone )
2016-08-26 22:51:17 +02:00
viewCell + + ;
2016-09-23 07:52:53 +02:00
championPtr - > _cell = ( ViewCell ) _vm - > normalizeModulo4 ( viewCell + dungeon . _partyDir ) ;
2016-09-09 07:32:32 +02:00
championPtr - > _attributes = kDMAttributeIcon ;
2016-09-23 07:52:53 +02:00
championPtr - > _directionMaximumDamageReceived = dungeon . _partyDir ;
2016-08-26 22:51:17 +02:00
championPtr - > _food = 1500 + _vm - > getRandomNumber ( 256 ) ;
championPtr - > _water = 1500 + _vm - > getRandomNumber ( 256 ) ;
2016-09-10 11:47:36 +02:00
for ( int16 slotIdx = kDMSlotReadyHand ; slotIdx < kDMSlotChest1 ; slotIdx + + )
2017-01-31 18:15:31 +01:00
championPtr - > _slots [ slotIdx ] = _vm - > _thingNone ;
2016-08-26 22:51:17 +02:00
2016-09-23 07:52:53 +02:00
Thing curThing = dungeon . getSquareFirstThing ( dungeon . _partyMapX , dungeon . _partyMapY ) ;
2016-09-11 00:33:54 +02:00
while ( curThing . getType ( ) ! = kDMstringTypeText )
2016-09-23 07:52:53 +02:00
curThing = dungeon . getNextThing ( curThing ) ;
2016-08-26 22:51:17 +02:00
char L0807_ac_DecodedChampionText [ 77 ] ;
char * decodedStringPtr = L0807_ac_DecodedChampionText ;
2016-09-23 07:52:53 +02:00
dungeon . decodeText ( decodedStringPtr , curThing , ( TextType ) ( kDMTextTypeScroll | kDMMaskDecodeEvenIfInvisible ) ) ;
2016-08-26 22:51:17 +02:00
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 ' )
2016-09-09 07:32:32 +02:00
setFlag ( championPtr - > _attributes , kDMAttributeMale ) ;
2016-08-26 22:51:17 +02:00
decodedStringPtr + + ;
2016-08-23 07:54:16 +02:00
championPtr - > _currHealth = championPtr - > _maxHealth = getDecodedValue ( decodedStringPtr , 4 ) ;
2016-08-26 22:51:17 +02:00
decodedStringPtr + = 4 ;
2016-08-23 07:54:16 +02:00
championPtr - > _currStamina = championPtr - > _maxStamina = getDecodedValue ( decodedStringPtr , 4 ) ;
2016-08-26 22:51:17 +02:00
decodedStringPtr + = 4 ;
2016-08-23 07:54:16 +02:00
championPtr - > _currMana = championPtr - > _maxMana = getDecodedValue ( decodedStringPtr , 4 ) ;
2016-08-26 22:51:17 +02:00
decodedStringPtr + = 4 ;
decodedStringPtr + + ;
2016-09-09 07:32:32 +02:00
for ( int16 statIdx = kDMStatLuck ; statIdx < = kDMStatAntifire ; statIdx + + ) {
championPtr - > _statistics [ statIdx ] [ kDMStatMinimum ] = 30 ;
championPtr - > _statistics [ statIdx ] [ kDMStatCurrent ] = championPtr - > _statistics [ statIdx ] [ kDMStatMaximum ] = getDecodedValue ( decodedStringPtr , 2 ) ;
2016-08-26 22:51:17 +02:00
decodedStringPtr + = 2 ;
}
2016-09-09 07:32:32 +02:00
championPtr - > _statistics [ kDMStatLuck ] [ kDMStatMinimum ] = 10 ;
2016-08-26 22:51:17 +02:00
decodedStringPtr + + ;
2016-09-09 07:32:32 +02:00
for ( uint16 skillIdx = kDMSkillSwing ; skillIdx < = kDMSkillWater ; skillIdx + + ) {
2016-08-26 22:51:17 +02:00
int skillValue = * decodedStringPtr + + - ' A ' ;
if ( skillValue > 0 )
championPtr - > _skills [ skillIdx ] . _experience = 125L < < skillValue ;
}
2016-09-09 07:32:32 +02:00
for ( uint16 skillIdx = kDMSkillFighter ; skillIdx < = kDMSkillWizard ; skillIdx + + ) {
2016-08-26 22:51:17 +02:00
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 ;
}
2016-08-23 07:54:16 +02:00
_candidateChampionOrdinal = previousPartyChampionCount + 1 ;
if ( + + _partyChampionCount = = 1 ) {
2016-09-09 07:12:36 +02:00
_vm - > _eventMan - > commandSetLeader ( kDMChampionFirst ) ;
2016-08-25 21:59:02 +02:00
_vm - > _menuMan - > _refreshActionArea = true ;
2016-08-26 22:51:17 +02:00
} else {
2016-08-25 21:59:02 +02:00
_vm - > _menuMan - > clearActingChampion ( ) ;
_vm - > _menuMan - > drawActionIcon ( ( ChampionIndex ) ( _partyChampionCount - 1 ) ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-23 07:52:53 +02:00
int16 curMapX = dungeon . _partyMapX ;
int16 curMapY = dungeon . _partyMapY ;
uint16 championObjectsCell = _vm - > returnOppositeDir ( dungeon . _partyDir ) ;
2017-11-08 16:46:05 -06:00
curMapX + = _vm - > _dirIntoStepCountEast [ dungeon . _partyDir ] ;
curMapY + = _vm - > _dirIntoStepCountNorth [ dungeon . _partyDir ] ;
2016-09-23 07:52:53 +02:00
curThing = dungeon . getSquareFirstThing ( curMapX , curMapY ) ;
2016-09-10 11:47:36 +02:00
int16 slotIdx = kDMSlotBackpackLine1_1 ;
2017-01-31 18:15:31 +01:00
while ( curThing ! = _vm - > _thingEndOfList ) {
2016-08-26 22:51:17 +02:00
ThingType thingType = curThing . getType ( ) ;
2016-09-11 00:33:54 +02:00
if ( ( thingType > kDMThingTypeSensor ) & & ( curThing . getCell ( ) = = championObjectsCell ) ) {
2016-09-23 07:52:53 +02:00
int16 objectAllowedSlots = dungeon . _objectInfos [ dungeon . getObjectInfoIndex ( curThing ) ] . _allowedSlots ;
2016-09-10 11:47:36 +02:00
uint16 curSlotIndex = kDMSlotReadyHand ;
2016-08-26 22:51:17 +02:00
switch ( thingType ) {
2016-09-11 00:33:54 +02:00
case kDMThingTypeArmour : {
2016-08-26 22:51:17 +02:00
bool skipCheck = false ;
2016-09-10 11:47:36 +02:00
for ( curSlotIndex = kDMSlotHead ; curSlotIndex < = kDMSlotFeet ; curSlotIndex + + ) {
2016-08-21 14:25:06 +02:00
if ( objectAllowedSlots & _slotMasks [ curSlotIndex ] ) {
2016-08-26 22:51:17 +02:00
skipCheck = true ;
break ;
}
}
if ( skipCheck )
break ;
2017-01-31 18:15:31 +01:00
if ( ( objectAllowedSlots & _slotMasks [ kDMSlotNeck ] ) & & ( championPtr - > _slots [ kDMSlotNeck ] = = _vm - > _thingNone ) )
2016-09-10 11:47:36 +02:00
curSlotIndex = kDMSlotNeck ;
2016-08-26 22:51:17 +02:00
else
curSlotIndex = slotIdx + + ;
break ;
}
2016-09-11 00:33:54 +02:00
case kDMThingTypeWeapon :
2017-01-31 18:15:31 +01:00
if ( championPtr - > _slots [ kDMSlotActionHand ] = = _vm - > _thingNone )
2016-09-10 11:47:36 +02:00
curSlotIndex = kDMSlotActionHand ;
2017-01-31 18:15:31 +01:00
else if ( ( objectAllowedSlots & _slotMasks [ kDMSlotNeck ] ) & & ( championPtr - > _slots [ kDMSlotNeck ] = = _vm - > _thingNone ) )
2016-09-10 11:47:36 +02:00
curSlotIndex = kDMSlotNeck ;
2016-08-26 22:51:17 +02:00
else
curSlotIndex = slotIdx + + ;
break ;
2016-09-11 00:33:54 +02:00
case kDMThingTypeScroll :
case kDMThingTypePotion :
2017-01-31 18:15:31 +01:00
if ( championPtr - > _slots [ kDMSlotPouch1 ] = = _vm - > _thingNone )
2016-09-10 11:47:36 +02:00
curSlotIndex = kDMSlotPouch1 ;
2017-01-31 18:15:31 +01:00
else if ( championPtr - > _slots [ kDMSlotPouch_2 ] = = _vm - > _thingNone )
2016-09-10 11:47:36 +02:00
curSlotIndex = kDMSlotPouch_2 ;
2017-01-31 18:15:31 +01:00
else if ( ( objectAllowedSlots & _slotMasks [ kDMSlotNeck ] ) & & ( championPtr - > _slots [ kDMSlotNeck ] = = _vm - > _thingNone ) )
2016-09-10 11:47:36 +02:00
curSlotIndex = kDMSlotNeck ;
2016-08-26 22:51:17 +02:00
else
curSlotIndex = slotIdx + + ;
break ;
2016-09-11 00:33:54 +02:00
case kDMThingTypeContainer :
case kDMThingTypeJunk :
2017-01-31 18:15:31 +01:00
if ( ( objectAllowedSlots & _slotMasks [ kDMSlotNeck ] ) & & ( championPtr - > _slots [ kDMSlotNeck ] = = _vm - > _thingNone ) )
2016-09-10 11:47:36 +02:00
curSlotIndex = kDMSlotNeck ;
2016-08-26 22:51:17 +02:00
else
curSlotIndex = slotIdx + + ;
break ;
default :
break ;
}
2017-01-31 18:15:31 +01:00
while ( championPtr - > _slots [ curSlotIndex ] ! = _vm - > _thingNone ) {
if ( ( objectAllowedSlots & _slotMasks [ kDMSlotNeck ] ) & & ( championPtr - > _slots [ kDMSlotNeck ] = = _vm - > _thingNone ) )
2016-09-10 11:47:36 +02:00
curSlotIndex = kDMSlotNeck ;
2016-08-26 22:51:17 +02:00
else
curSlotIndex = slotIdx + + ;
}
2016-08-23 07:54:16 +02:00
addObjectInSlot ( ( ChampionIndex ) previousPartyChampionCount , curThing , ( ChampionSlot ) curSlotIndex ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-23 07:52:53 +02:00
curThing = dungeon . getNextThing ( curThing ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-25 21:25:18 +02:00
_vm - > _inventoryMan - > toggleInventory ( ( ChampionIndex ) previousPartyChampionCount ) ;
2017-04-18 06:47:50 +02:00
_vm - > _menuMan - > drawDisabledMenu ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : drawChampionBarGraphs ( ChampionIndex champIndex ) {
Champion * champ = & _champions [ champIndex ] ;
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
2016-09-25 22:33:40 +02:00
DisplayMan & display = * _vm - > _displayMan ;
2016-09-25 07:42:35 +02:00
int16 barGraphHeights [ 3 ] ;
2016-08-26 22:51:17 +02:00
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 ;
}
2016-09-25 07:42:35 +02:00
evtMan . showMouse ( ) ;
2016-08-26 22:51:17 +02:00
// Strangerke - TO CHECK: if portraits, maybe the old (assembly) code is required for older versions
Box box ;
2016-09-18 11:46:53 +02:00
box . _rect . left = champIndex * kDMChampionStatusBoxSpacing + 46 ;
2016-09-16 21:17:02 +02:00
box . _rect . right = box . _rect . left + 3 ;
box . _rect . top = 2 ;
box . _rect . bottom = 26 ;
2016-08-26 22:51:17 +02:00
for ( int16 barGraphIndex = 0 ; barGraphIndex < 3 ; barGraphIndex + + ) {
int16 barGraphHeight = barGraphHeights [ barGraphIndex ] ;
if ( barGraphHeight < 25 ) {
2016-09-16 21:17:02 +02:00
box . _rect . top = 2 ;
box . _rect . bottom = 27 - barGraphHeight ;
2016-09-25 22:33:40 +02:00
display . fillScreenBox ( box , kDMColorDarkestGray ) ;
2016-08-26 22:51:17 +02:00
}
if ( barGraphHeight ) {
2016-09-16 21:17:02 +02:00
box . _rect . top = 27 - barGraphHeight ;
box . _rect . bottom = 26 ;
2016-09-25 22:33:40 +02:00
display . fillScreenBox ( box , _championColor [ champIndex ] ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-16 21:17:02 +02:00
box . _rect . left + = 7 ;
box . _rect . right + = 7 ;
2016-08-26 22:51:17 +02:00
}
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
uint16 ChampionMan : : getStaminaAdjustedValue ( Champion * champ , int16 val ) {
2016-08-26 22:51:17 +02:00
int16 currStamina = champ - > _currStamina ;
int16 halfMaxStamina = champ - > _maxStamina / 2 ;
if ( currStamina < halfMaxStamina ) {
val / = 2 ;
return val + ( ( uint32 ) val * ( uint32 ) currStamina ) / halfMaxStamina ;
}
return val ;
}
2016-08-23 07:54:16 +02:00
uint16 ChampionMan : : getMaximumLoad ( Champion * champ ) {
2016-09-09 07:32:32 +02:00
uint16 maximumLoad = champ - > getStatistic ( kDMStatStrength , kDMStatCurrent ) * 8 + 100 ;
2016-08-23 07:54:16 +02:00
maximumLoad = getStaminaAdjustedValue ( champ , maximumLoad ) ;
2016-08-26 22:51:17 +02:00
int16 wounds = champ - > getWounds ( ) ;
if ( wounds )
2016-09-09 07:32:32 +02:00
maximumLoad - = maximumLoad > > ( champ - > getWoundsFlag ( kDMWoundLegs ) ? 2 : 3 ) ;
2016-08-26 22:51:17 +02:00
2016-09-10 11:47:36 +02:00
if ( _vm - > _objectMan - > getIconIndex ( champ - > getSlot ( kDMSlotFeet ) ) = = kDMIconIndiceArmourElvenBoots )
2016-08-26 22:51:17 +02:00
maximumLoad + = maximumLoad * 16 ;
maximumLoad + = 9 ;
maximumLoad - = maximumLoad % 10 ;
return maximumLoad ;
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : drawChampionState ( ChampionIndex champIndex ) {
2016-09-10 21:50:57 +02:00
static Box boxMouth = Box ( 55 , 72 , 12 , 29 ) ; // @ G0048_s_Graphic562_Box_Mouth
static Box boxEye = Box ( 11 , 28 , 12 , 29 ) ; // @ G0049_s_Graphic562_Box_Eye
2016-08-18 21:18:08 +02:00
2016-09-18 11:46:53 +02:00
int16 championStatusBoxX = champIndex * kDMChampionStatusBoxSpacing ;
2016-08-23 07:54:16 +02:00
Champion * curChampion = & _champions [ champIndex ] ;
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
TextMan & txtMan = * _vm - > _textMan ;
2016-09-25 22:33:40 +02:00
DisplayMan & display = * _vm - > _displayMan ;
2016-09-26 21:12:51 +02:00
InventoryMan & inventory = * _vm - > _inventoryMan ;
2016-09-25 07:42:35 +02:00
2016-08-26 22:51:17 +02:00
uint16 championAttributes = curChampion - > _attributes ;
2016-09-09 07:32:32 +02:00
if ( ! getFlag ( championAttributes , kDMAttributeNameTitle | kDMAttributeStatistics | kDMAttributeLoad | kDMAttributeIcon | kDMAttributePanel | kDMAttributeStatusBox | kDMAttributeWounds | kDMAttributeViewport | kDMAttributeActionHand ) )
2016-08-26 22:51:17 +02:00
return ;
2016-09-26 21:12:51 +02:00
bool isInventoryChampion = ( _vm - > indexToOrdinal ( champIndex ) = = inventory . _inventoryChampionOrdinal ) ;
2016-09-25 22:33:40 +02:00
display . _useByteBoxCoordinates = false ;
2016-09-25 07:42:35 +02:00
evtMan . showMouse ( ) ;
2016-09-09 07:32:32 +02:00
if ( getFlag ( championAttributes , kDMAttributeStatusBox ) ) {
2016-08-26 22:51:17 +02:00
Box box ;
2016-09-16 21:17:02 +02:00
box . _rect . top = 0 ;
box . _rect . bottom = 28 ;
box . _rect . left = championStatusBoxX ;
box . _rect . right = box . _rect . left + 66 ;
2016-08-26 22:51:17 +02:00
if ( curChampion - > _currHealth ) {
2016-09-25 22:33:40 +02:00
display . fillScreenBox ( box , kDMColorDarkestGray ) ;
2016-08-26 22:51:17 +02:00
int16 nativeBitmapIndices [ 3 ] ;
for ( uint16 i = 0 ; i < 3 ; + + i )
nativeBitmapIndices [ i ] = 0 ;
uint16 borderCount = 0 ;
2016-08-23 07:54:16 +02:00
if ( _party . _fireShieldDefense > 0 )
2016-09-21 07:53:54 +02:00
nativeBitmapIndices [ borderCount + + ] = kDMGraphicIdxBorderPartyFireshield ;
2016-08-26 22:51:17 +02:00
2016-08-23 07:54:16 +02:00
if ( _party . _spellShieldDefense > 0 )
2016-09-21 07:53:54 +02:00
nativeBitmapIndices [ borderCount + + ] = kDMGraphicIdxBorderPartySpellshield ;
2016-08-26 22:51:17 +02:00
2016-08-23 07:54:16 +02:00
if ( ( _party . _shieldDefense > 0 ) | | curChampion - > _shieldDefense )
2016-09-21 07:53:54 +02:00
nativeBitmapIndices [ borderCount + + ] = kDMGraphicIdxBorderPartyShield ;
2016-08-26 22:51:17 +02:00
while ( borderCount - - )
2016-09-25 22:33:40 +02:00
display . blitToScreen ( display . getNativeBitmapOrGraphic ( nativeBitmapIndices [ borderCount ] ) , & box , k40_byteWidth , kDMColorFlesh , 29 ) ;
2016-08-26 22:51:17 +02:00
if ( isInventoryChampion ) {
2016-09-26 21:12:51 +02:00
inventory . drawStatusBoxPortrait ( champIndex ) ;
2016-09-09 07:32:32 +02:00
setFlag ( championAttributes , kDMAttributeStatistics ) ;
2016-08-26 22:51:17 +02:00
} else
2016-09-09 07:32:32 +02:00
setFlag ( championAttributes , kDMAttributeNameTitle | kDMAttributeStatistics | kDMAttributeWounds | kDMAttributeActionHand ) ;
2016-08-26 22:51:17 +02:00
} else {
2016-09-25 22:33:40 +02:00
display . blitToScreen ( display . getNativeBitmapOrGraphic ( kDMGraphicIdxStatusBoxDeadChampion ) , & box , k40_byteWidth , kDMColorNoTransparency , 29 ) ;
2016-09-25 07:42:35 +02:00
txtMan . printToLogicalScreen ( championStatusBoxX + 1 , 5 , kDMColorLightestGray , kDMColorDarkGary , curChampion - > _name ) ;
2016-08-25 21:59:02 +02:00
_vm - > _menuMan - > drawActionIcon ( champIndex ) ;
2016-08-26 22:51:17 +02:00
2016-09-09 07:32:32 +02:00
clearFlag ( curChampion - > _attributes , kDMAttributeNameTitle | kDMAttributeStatistics | kDMAttributeLoad | kDMAttributeIcon | kDMAttributePanel | kDMAttributeStatusBox | kDMAttributeWounds | kDMAttributeViewport | kDMAttributeActionHand ) ;
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
return ;
}
}
if ( ! ( curChampion - > _currHealth ) ) {
2016-09-09 07:32:32 +02:00
clearFlag ( curChampion - > _attributes , kDMAttributeNameTitle | kDMAttributeStatistics | kDMAttributeLoad | kDMAttributeIcon | kDMAttributePanel | kDMAttributeStatusBox | kDMAttributeWounds | kDMAttributeViewport | kDMAttributeActionHand ) ;
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
return ;
}
2016-09-09 07:32:32 +02:00
if ( getFlag ( championAttributes , kDMAttributeNameTitle ) ) {
2016-09-16 07:46:10 +02:00
Color nameColor = ( champIndex = = _leaderIndex ) ? kDMColorGold : kDMColorLightestGray ;
2016-08-26 22:51:17 +02:00
if ( isInventoryChampion ) {
char * championName = curChampion - > _name ;
2016-09-25 07:42:35 +02:00
txtMan . printToViewport ( 3 , 7 , nameColor , championName ) ;
2016-08-26 22:51:17 +02:00
int16 championTitleX = 6 * strlen ( championName ) + 3 ;
char titleFirstCharacter = curChampion - > _title [ 0 ] ;
if ( ( titleFirstCharacter ! = ' , ' ) & & ( titleFirstCharacter ! = ' ; ' ) & & ( titleFirstCharacter ! = ' - ' ) )
championTitleX + = 6 ;
2016-09-25 07:42:35 +02:00
txtMan . printToViewport ( championTitleX , 7 , nameColor , curChampion - > _title ) ;
2016-09-09 07:32:32 +02:00
setFlag ( championAttributes , kDMAttributeViewport ) ;
2016-08-26 22:51:17 +02:00
} else {
Box box ;
2016-09-16 21:17:02 +02:00
box . _rect . top = 0 ;
box . _rect . bottom = 6 ;
box . _rect . left = championStatusBoxX ;
box . _rect . right = box . _rect . left + 42 ;
2016-09-25 22:33:40 +02:00
display . fillScreenBox ( box , kDMColorDarkGary ) ;
2016-09-25 07:42:35 +02:00
txtMan . printToLogicalScreen ( championStatusBoxX + 1 , 5 , nameColor , kDMColorDarkGary , curChampion - > _name ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-09-09 07:32:32 +02:00
if ( getFlag ( championAttributes , kDMAttributeStatistics ) ) {
2016-08-23 07:54:16 +02:00
drawChampionBarGraphs ( champIndex ) ;
2016-08-26 22:51:17 +02:00
if ( isInventoryChampion ) {
2016-08-23 07:54:16 +02:00
drawHealthStaminaManaValues ( curChampion ) ;
2016-08-26 22:51:17 +02:00
int16 nativeBitmapIndex ;
if ( ( curChampion - > _food < 0 ) | | ( curChampion - > _water < 0 ) | | ( curChampion - > _poisonEventCount ) )
2016-09-21 07:53:54 +02:00
nativeBitmapIndex = kDMGraphicIdxSlotBoxWounded ;
2016-08-26 22:51:17 +02:00
else
2016-09-21 07:53:54 +02:00
nativeBitmapIndex = kDMGraphicIdxSlotBoxNormal ;
2016-08-26 22:51:17 +02:00
2016-09-25 22:33:40 +02:00
display . blitToViewport ( display . getNativeBitmapOrGraphic ( nativeBitmapIndex ) , boxMouth , k16_byteWidth , kDMColorDarkestGray , 18 ) ;
2016-09-21 07:53:54 +02:00
nativeBitmapIndex = kDMGraphicIdxSlotBoxNormal ;
2016-09-09 07:32:32 +02:00
for ( int i = kDMStatStrength ; i < = kDMStatAntifire ; i + + ) {
if ( ( curChampion - > _statistics [ i ] [ kDMStatCurrent ] < curChampion - > _statistics [ i ] [ kDMStatMaximum ] ) ) {
2016-09-21 07:53:54 +02:00
nativeBitmapIndex = kDMGraphicIdxSlotBoxWounded ;
2016-08-26 22:51:17 +02:00
break ;
}
}
2016-09-25 22:33:40 +02:00
display . blitToViewport ( display . getNativeBitmapOrGraphic ( nativeBitmapIndex ) , boxEye , k16_byteWidth , kDMColorDarkestGray , 18 ) ;
2016-09-09 07:32:32 +02:00
setFlag ( championAttributes , kDMAttributeViewport ) ;
2016-08-26 22:51:17 +02:00
}
}
2016-09-09 07:32:32 +02:00
if ( getFlag ( championAttributes , kDMAttributeWounds ) ) {
2016-09-10 11:47:36 +02:00
for ( int i = isInventoryChampion ? kDMSlotFeet : kDMSlotActionHand ; i > = kDMSlotReadyHand ; i - - )
2016-08-23 07:54:16 +02:00
drawSlot ( champIndex , i ) ;
2016-08-26 22:51:17 +02:00
if ( isInventoryChampion )
2016-09-09 07:32:32 +02:00
setFlag ( championAttributes , kDMAttributeViewport ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-09 07:32:32 +02:00
if ( getFlag ( championAttributes , kDMAttributeLoad ) & & isInventoryChampion ) {
2016-08-23 07:54:16 +02:00
uint16 maxLoad = getMaximumLoad ( curChampion ) ;
2016-08-26 22:51:17 +02:00
Color loadColor ;
if ( curChampion - > _load > maxLoad )
2016-09-16 07:46:10 +02:00
loadColor = kDMColorRed ;
2016-08-26 22:51:17 +02:00
else if ( ( ( long ) curChampion - > _load < < 3 ) > ( ( long ) maxLoad * 5 ) )
2016-09-16 07:46:10 +02:00
loadColor = kDMColorYellow ;
2016-08-26 22:51:17 +02:00
else
2016-09-16 07:46:10 +02:00
loadColor = kDMColorLightestGray ;
2016-08-26 22:51:17 +02:00
2016-08-15 20:25:40 +02:00
switch ( _vm - > getGameLanguage ( ) ) { // localized
default :
2016-09-25 07:42:35 +02:00
case Common : : EN_ANY :
txtMan . printToViewport ( 104 , 132 , loadColor , " LOAD " ) ;
break ;
case Common : : DE_DEU :
txtMan . printToViewport ( 104 , 132 , loadColor , " LAST " ) ;
break ;
case Common : : FR_FRA :
txtMan . printToViewport ( 104 , 132 , loadColor , " CHARGE " ) ;
break ;
2016-08-15 20:25:40 +02:00
}
2016-08-26 22:51:17 +02:00
maxLoad = curChampion - > _load / 10 ;
2016-08-23 23:36:18 +02:00
strcpy ( _vm - > _stringBuildBuffer , getStringFromInteger ( maxLoad , true , 3 ) . c_str ( ) ) ;
2016-08-15 20:25:40 +02:00
switch ( _vm - > getGameLanguage ( ) ) { // localized
default :
2016-08-23 23:36:18 +02:00
case Common : : EN_ANY : strcat ( _vm - > _stringBuildBuffer , " . " ) ; break ;
case Common : : DE_DEU : strcat ( _vm - > _stringBuildBuffer , " , " ) ; break ;
case Common : : FR_FRA : strcat ( _vm - > _stringBuildBuffer , " KG, " ) ; break ;
2016-08-15 20:25:40 +02:00
}
2016-08-26 22:51:17 +02:00
maxLoad = curChampion - > _load - ( maxLoad * 10 ) ;
2016-08-23 23:36:18 +02:00
strcat ( _vm - > _stringBuildBuffer , getStringFromInteger ( maxLoad , false , 1 ) . c_str ( ) ) ;
strcat ( _vm - > _stringBuildBuffer , " / " ) ;
2016-08-23 07:54:16 +02:00
maxLoad = ( getMaximumLoad ( curChampion ) + 5 ) / 10 ;
2016-08-23 23:36:18 +02:00
strcat ( _vm - > _stringBuildBuffer , getStringFromInteger ( maxLoad , true , 3 ) . c_str ( ) ) ;
strcat ( _vm - > _stringBuildBuffer , " KG " ) ;
2016-09-25 07:42:35 +02:00
txtMan . printToViewport ( 148 , 132 , loadColor , _vm - > _stringBuildBuffer ) ;
2016-09-09 07:32:32 +02:00
setFlag ( championAttributes , kDMAttributeViewport ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-23 07:52:53 +02:00
DungeonMan & dungeon = * _vm - > _dungeonMan ;
uint16 championIconIndex = getChampionIconIndex ( curChampion - > _cell , dungeon . _partyDir ) ;
2016-09-25 07:42:35 +02:00
if ( getFlag ( championAttributes , kDMAttributeIcon ) & & ( evtMan . _useChampionIconOrdinalAsMousePointerBitmap ! = _vm - > indexToOrdinal ( championIconIndex ) ) ) {
2016-09-25 22:33:40 +02:00
display . fillScreenBox ( _boxChampionIcons [ championIconIndex ] , _championColor [ champIndex ] ) ;
display . blitToBitmap ( display . getNativeBitmapOrGraphic ( kDMGraphicIdxChampionIcons ) , display . _bitmapScreen , _boxChampionIcons [ championIconIndex ] , getChampionIconIndex ( curChampion - > _dir , dungeon . _partyDir ) * 19 , 0 , k40_byteWidth , k160_byteWidthScreen , kDMColorDarkestGray , 14 , k200_heightScreen ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-09 07:32:32 +02:00
if ( getFlag ( championAttributes , kDMAttributePanel ) & & isInventoryChampion ) {
2016-08-23 23:36:18 +02:00
if ( _vm - > _pressingMouth )
2016-09-26 21:12:51 +02:00
inventory . drawPanelFoodWaterPoisoned ( ) ;
2016-08-23 23:36:18 +02:00
else if ( _vm - > _pressingEye ) {
2016-08-23 07:54:16 +02:00
if ( _leaderEmptyHanded )
2016-09-26 21:12:51 +02:00
inventory . drawChampionSkillsAndStatistics ( ) ;
2016-08-26 22:51:17 +02:00
} else
2016-09-26 21:12:51 +02:00
inventory . drawPanel ( ) ;
2016-08-26 22:51:17 +02:00
2016-09-09 07:32:32 +02:00
setFlag ( championAttributes , kDMAttributeViewport ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-09 07:32:32 +02:00
if ( getFlag ( championAttributes , kDMAttributeActionHand ) ) {
2016-09-10 11:47:36 +02:00
drawSlot ( champIndex , kDMSlotActionHand ) ;
2016-08-25 21:59:02 +02:00
_vm - > _menuMan - > drawActionIcon ( champIndex ) ;
2016-08-26 22:51:17 +02:00
if ( isInventoryChampion )
2016-09-09 07:32:32 +02:00
setFlag ( championAttributes , kDMAttributeViewport ) ;
2016-08-26 22:51:17 +02:00
}
2016-09-09 07:32:32 +02:00
if ( getFlag ( championAttributes , kDMAttributeViewport ) )
2016-09-25 22:33:40 +02:00
display . drawViewport ( k0_viewportNotDungeonView ) ;
2016-08-26 22:51:17 +02:00
2016-09-09 07:32:32 +02:00
clearFlag ( curChampion - > _attributes , kDMAttributeNameTitle | kDMAttributeStatistics | kDMAttributeLoad | kDMAttributeIcon | kDMAttributePanel | kDMAttributeStatusBox | kDMAttributeWounds | kDMAttributeViewport | kDMAttributeActionHand ) ;
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
uint16 ChampionMan : : getChampionIconIndex ( int16 val , Direction dir ) {
2016-08-26 22:51:17 +02:00
return ( ( val + 4 - dir ) & 0x3 ) ;
}
2016-08-27 10:54:29 +02:00
void ChampionMan : : drawHealthStaminaManaValues ( Champion * champ ) {
2016-08-23 07:54:16 +02:00
drawHealthOrStaminaOrManaValue ( 116 , champ - > _currHealth , champ - > _maxHealth ) ;
drawHealthOrStaminaOrManaValue ( 124 , champ - > _currStamina , champ - > _maxStamina ) ;
drawHealthOrStaminaOrManaValue ( 132 , champ - > _currMana , champ - > _maxMana ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-23 07:54:16 +02:00
void ChampionMan : : drawSlot ( uint16 champIndex , int16 slotIndex ) {
Champion * champ = & _champions [ champIndex ] ;
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
2016-09-25 22:33:40 +02:00
DisplayMan & display = * _vm - > _displayMan ;
2016-09-26 21:12:51 +02:00
InventoryMan & inventory = * _vm - > _inventoryMan ;
2016-09-25 07:42:35 +02:00
int16 nativeBitmapIndex = - 1 ;
2016-09-26 21:12:51 +02:00
bool isInventoryChamp = ( inventory . _inventoryChampionOrdinal = = _vm - > indexToOrdinal ( champIndex ) ) ;
2016-08-26 22:51:17 +02:00
uint16 slotBoxIndex ;
if ( ! isInventoryChamp ) {
// If drawing a slot for a champion other than the champion whose inventory is open
2016-09-10 11:47:36 +02:00
if ( ( slotIndex > kDMSlotActionHand ) | | ( _candidateChampionOrdinal = = _vm - > indexToOrdinal ( champIndex ) ) )
2016-08-26 22:51:17 +02:00
return ;
slotBoxIndex = ( champIndex < < 1 ) + slotIndex ;
} else
2016-09-18 22:15:51 +02:00
slotBoxIndex = kDMSlotBoxInventoryFirstSlot + slotIndex ;
2016-08-26 22:51:17 +02:00
Thing thing ;
2016-09-10 11:47:36 +02:00
if ( slotIndex > = kDMSlotChest1 )
2016-09-26 21:12:51 +02:00
thing = inventory . _chestSlots [ slotIndex - kDMSlotChest1 ] ;
2016-08-26 22:51:17 +02:00
else
thing = champ - > getSlot ( ( ChampionSlot ) slotIndex ) ;
2016-08-25 22:19:34 +02:00
SlotBox * slotBox = & _vm - > _objectMan - > _slotBoxes [ slotBoxIndex ] ;
2016-08-26 22:51:17 +02:00
Box box ;
2016-09-16 21:17:02 +02:00
box . _rect . left = slotBox - > _x - 1 ;
box . _rect . top = slotBox - > _y - 1 ;
box . _rect . right = box . _rect . left + 17 ;
box . _rect . bottom = box . _rect . top + 17 ;
2016-08-26 22:51:17 +02:00
if ( ! isInventoryChamp )
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
int16 iconIndex ;
2017-01-31 18:15:31 +01:00
if ( thing = = _vm - > _thingNone ) {
2016-09-10 11:47:36 +02:00
if ( slotIndex < = kDMSlotFeet ) {
2016-09-09 07:12:36 +02:00
iconIndex = kDMIconIndiceReadyHand + ( slotIndex < < 1 ) ;
2016-08-26 22:51:17 +02:00
if ( champ - > getWoundsFlag ( ( ChampionWound ) ( 1 < < slotIndex ) ) ) {
iconIndex + + ;
2016-09-21 07:53:54 +02:00
nativeBitmapIndex = kDMGraphicIdxSlotBoxWounded ;
2016-08-26 22:51:17 +02:00
} else
2016-09-21 07:53:54 +02:00
nativeBitmapIndex = kDMGraphicIdxSlotBoxNormal ;
2016-08-26 22:51:17 +02:00
} else {
2016-09-10 11:47:36 +02:00
if ( ( slotIndex > = kDMSlotNeck ) & & ( slotIndex < = kDMSlotBackpackLine1_1 ) )
iconIndex = kDMIconIndiceNeck + ( slotIndex - kDMSlotNeck ) ;
2016-08-26 22:51:17 +02:00
else
2016-09-09 07:12:36 +02:00
iconIndex = kDMIconIndiceEmptyBox ;
2016-08-26 22:51:17 +02:00
}
} else {
2016-08-25 22:19:34 +02:00
iconIndex = _vm - > _objectMan - > getIconIndex ( thing ) ; // BUG0_35
2016-09-10 11:47:36 +02:00
if ( isInventoryChamp & & ( slotIndex = = kDMSlotActionHand ) & & ( ( iconIndex = = kDMIconIndiceContainerChestClosed ) | | ( iconIndex = = kDMIconIndiceScrollOpen ) ) ) {
2016-08-26 22:51:17 +02:00
iconIndex + + ;
} // BUG2_00
2016-09-10 11:47:36 +02:00
if ( slotIndex < = kDMSlotFeet ) {
2016-08-26 22:51:17 +02:00
if ( champ - > getWoundsFlag ( ( ChampionWound ) ( 1 < < slotIndex ) ) )
2016-09-21 07:53:54 +02:00
nativeBitmapIndex = kDMGraphicIdxSlotBoxWounded ;
2016-08-26 22:51:17 +02:00
else
2016-09-21 07:53:54 +02:00
nativeBitmapIndex = kDMGraphicIdxSlotBoxNormal ;
2016-08-26 22:51:17 +02:00
}
}
2016-09-10 11:47:36 +02:00
if ( ( slotIndex = = kDMSlotActionHand ) & & ( _vm - > indexToOrdinal ( champIndex ) = = _actingChampionOrdinal ) )
2016-09-21 07:53:54 +02:00
nativeBitmapIndex = kDMGraphicIdxSlotBoxActingHand ;
2016-08-26 22:51:17 +02:00
if ( nativeBitmapIndex ! = - 1 ) {
2016-09-25 22:33:40 +02:00
display . _useByteBoxCoordinates = false ;
2016-08-12 14:55:35 +02:00
if ( isInventoryChamp ) {
2016-09-25 22:33:40 +02:00
display . blitToBitmap ( display . getNativeBitmapOrGraphic ( nativeBitmapIndex ) ,
display . _bitmapViewport , box , 0 , 0 , 16 , k112_byteWidthViewport ,
kDMColorDarkestGray , display . getPixelHeight ( nativeBitmapIndex ) , k136_heightViewport ) ;
2016-08-12 14:55:35 +02:00
} else {
2016-09-25 22:33:40 +02:00
display . blitToBitmap ( display . getNativeBitmapOrGraphic ( nativeBitmapIndex ) ,
display . _bitmapScreen , box , 0 , 0 , 16 , k160_byteWidthScreen ,
kDMColorDarkestGray , display . getPixelHeight ( nativeBitmapIndex ) , k136_heightViewport ) ;
2016-08-12 14:55:35 +02:00
}
2016-08-26 22:51:17 +02:00
}
2016-08-25 22:19:34 +02:00
_vm - > _objectMan - > drawIconInSlotBox ( slotBoxIndex , iconIndex ) ;
2016-08-26 22:51:17 +02:00
if ( ! isInventoryChamp )
2016-09-25 07:42:35 +02:00
evtMan . showMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
2016-08-27 10:54:29 +02:00
void ChampionMan : : renameChampion ( Champion * champ ) {
2016-09-25 07:42:35 +02:00
# define kDMRenameChampionName 1
# define kDMRenameChampionTitle 2
2016-08-26 22:51:17 +02:00
static const char underscoreCharacterString [ 2 ] = " _ " ;
static char renameChampionInputCharacterString [ 2 ] = " " ;
static const char reincarnateSpecialCharacters [ 6 ] = { ' , ' , ' . ' , ' ; ' , ' : ' , ' ' } ;
2016-09-25 07:42:35 +02:00
EventManager & evtMan = * _vm - > _eventMan ;
TextMan & txtMan = * _vm - > _textMan ;
2016-09-25 22:33:40 +02:00
DisplayMan & display = * _vm - > _displayMan ;
2016-09-25 07:42:35 +02:00
2016-08-26 22:51:17 +02:00
Box displayBox ;
2016-09-16 21:17:02 +02:00
displayBox . _rect . top = 3 ;
displayBox . _rect . bottom = 8 ;
displayBox . _rect . left = 3 ;
displayBox . _rect . right = displayBox . _rect . left + 167 ;
2016-08-26 22:51:17 +02:00
2016-09-25 22:33:40 +02:00
display . fillBoxBitmap ( display . _bitmapViewport , displayBox , kDMColorDarkestGray , k112_byteWidthViewport , k136_heightViewport ) ;
display . blitToViewport ( display . getNativeBitmapOrGraphic ( kDMGraphicIdxPanelRenameChampion ) , _vm - > _inventoryMan - > _boxPanel , k72_byteWidth , kDMColorCyan , 73 ) ;
2016-09-25 07:42:35 +02:00
txtMan . printToViewport ( 177 , 58 , kDMColorLightestGray , " _______ " ) ;
txtMan . printToViewport ( 105 , 76 , kDMColorLightestGray , " ___________________ " ) ;
evtMan . showMouse ( ) ;
2016-09-25 22:33:40 +02:00
display . drawViewport ( k0_viewportNotDungeonView ) ;
2016-09-25 07:42:35 +02:00
evtMan . setMousePointerToNormal ( k0_pointerArrow ) ;
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
uint16 curCharacterIndex = 0 ;
champ - > _name [ curCharacterIndex ] = ' \0 ' ;
champ - > _title [ 0 ] = ' \0 ' ;
2016-09-25 07:42:35 +02:00
int16 renamedChampionStringMode = kDMRenameChampionName ;
2016-08-26 22:51:17 +02:00
char * renamedChampionString = champ - > _name ;
int16 textPosX = 177 ;
int16 textPosY = 91 ;
for ( ; ; ) { /*_Infinite loop_*/
2016-09-25 07:42:35 +02:00
bool championTitleIsFull = ( ( renamedChampionStringMode = = kDMRenameChampionTitle ) & & ( curCharacterIndex = = 19 ) ) ;
2016-08-26 22:51:17 +02:00
if ( ! championTitleIsFull ) {
2016-09-25 07:42:35 +02:00
evtMan . showMouse ( ) ;
2016-09-25 22:33:40 +02:00
txtMan . printTextToBitmap ( display . _bitmapScreen , k160_byteWidthScreen , textPosX , textPosY , kDMColorGold , kDMColorDarkestGray , underscoreCharacterString , k200_heightScreen ) ;
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
int16 curCharacter = 256 ;
while ( curCharacter = = 256 ) {
Common : : Event event ;
2016-09-25 07:42:35 +02:00
Common : : EventType eventType = evtMan . processInput ( & event , & event ) ;
2016-09-25 22:33:40 +02:00
display . updateScreen ( ) ;
2016-08-26 22:51:17 +02:00
if ( _vm - > _engineShouldQuit )
return ;
2016-09-25 22:33:40 +02:00
display . updateScreen ( ) ;
2016-08-26 22:51:17 +02:00
//_vm->f22_delay(1);
if ( eventType = = Common : : EVENT_LBUTTONDOWN ) {
// If left mouse button status has changed
2016-09-25 07:42:35 +02:00
Common : : Point mousePos = evtMan . getMousePos ( ) ;
if ( ( renamedChampionStringMode = = kDMRenameChampionTitle | | ( curCharacterIndex > 0 ) ) & & ( mousePos . x > = 197 ) & & ( mousePos . x < = 215 ) & & ( mousePos . y > = 147 ) & & ( mousePos . y < = 155 ) ) { /* Coordinates of 'OK' button */
2016-08-26 22:51:17 +02:00
int16 characterIndexBackup = curCharacterIndex ;
2016-09-12 20:50:40 +02:00
char championNameBackupString [ 8 ] ;
2016-08-26 22:51:17 +02:00
renamedChampionString = champ - > _name ;
2016-09-12 20:50:40 +02:00
strcpy ( championNameBackupString , renamedChampionString ) ;
2016-08-26 22:51:17 +02:00
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 ;
2016-09-09 07:12:36 +02:00
for ( uint16 idx = kDMChampionFirst ; idx < _partyChampionCount - 1 ; idx + + ) {
2016-08-23 07:54:16 +02:00
if ( ! strcmp ( _champions [ idx ] . _name , renamedChampionString ) ) {
2016-08-26 22:51:17 +02:00
// If an existing champion already has the specified name for the new champion
found = true ;
break ;
}
}
if ( ! found )
return ;
2016-09-25 07:42:35 +02:00
if ( renamedChampionStringMode = = kDMRenameChampionTitle )
2016-08-26 22:51:17 +02:00
renamedChampionString = champ - > _title ;
2016-09-12 20:50:40 +02:00
strcpy ( renamedChampionString = champ - > _name , championNameBackupString ) ;
2016-08-26 22:51:17 +02:00
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 ;
2016-09-25 07:42:35 +02:00
evtMan . showMouse ( ) ;
2016-09-25 22:33:40 +02:00
txtMan . printTextToBitmap ( display . _bitmapScreen , k160_byteWidthScreen , textPosX , textPosY , kDMColorLightestGray , kDMColorDarkestGray , renameChampionInputCharacterString , k200_heightScreen ) ;
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
renamedChampionString [ curCharacterIndex + + ] = curCharacter ;
renamedChampionString [ curCharacterIndex ] = ' \0 ' ;
textPosX + = 6 ;
2016-09-25 07:42:35 +02:00
if ( ( renamedChampionStringMode = = kDMRenameChampionName ) & & ( curCharacterIndex = = 7 ) ) {
renamedChampionStringMode = kDMRenameChampionTitle ;
2016-08-26 22:51:17 +02:00
renamedChampionString = champ - > _title ;
textPosX = 105 ;
textPosY = 109 ;
curCharacterIndex = 0 ;
}
}
}
} else if ( curCharacter = = ' \r ' ) { // Carriage return
2016-09-25 07:42:35 +02:00
if ( ( renamedChampionStringMode = = kDMRenameChampionName ) & & ( curCharacterIndex > 0 ) ) {
evtMan . showMouse ( ) ;
2016-09-25 22:33:40 +02:00
txtMan . printTextToBitmap ( display . _bitmapScreen , k160_byteWidthScreen , textPosX , textPosY , kDMColorLightestGray , kDMColorDarkestGray , underscoreCharacterString , k200_heightScreen ) ;
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
renamedChampionStringMode = kDMRenameChampionTitle ;
2016-08-26 22:51:17 +02:00
renamedChampionString = champ - > _title ;
textPosX = 105 ;
textPosY = 109 ;
curCharacterIndex = 0 ;
}
} else if ( curCharacter = = ' \b ' ) { // Backspace
2016-09-25 07:42:35 +02:00
if ( ( renamedChampionStringMode = = kDMRenameChampionName ) & & ( curCharacterIndex = = 0 ) )
2016-08-26 22:51:17 +02:00
continue ;
if ( ! championTitleIsFull ) {
2016-09-25 07:42:35 +02:00
evtMan . showMouse ( ) ;
2016-09-25 22:33:40 +02:00
txtMan . printTextToBitmap ( display . _bitmapScreen , k160_byteWidthScreen , textPosX , textPosY , kDMColorLightestGray , kDMColorDarkestGray , underscoreCharacterString , k200_heightScreen ) ;
2016-09-25 07:42:35 +02:00
evtMan . hideMouse ( ) ;
2016-08-26 22:51:17 +02:00
}
if ( curCharacterIndex = = 0 ) {
renamedChampionString = champ - > _name ;
curCharacterIndex = strlen ( renamedChampionString ) - 1 ;
2016-09-25 07:42:35 +02:00
renamedChampionStringMode = kDMRenameChampionName ;
2016-08-26 22:51:17 +02:00
textPosX = 177 + ( curCharacterIndex * 6 ) ;
textPosY = 91 ;
} else {
curCharacterIndex - - ;
textPosX - = 6 ;
}
renamedChampionString [ curCharacterIndex ] = ' \0 ' ;
}
}
}
2016-08-23 07:54:16 +02:00
uint16 ChampionMan : : getSkillLevel ( int16 champIndex , uint16 skillIndex ) {
if ( _partyIsSleeping )
2016-08-26 22:51:17 +02:00
return 1 ;
2016-09-09 07:12:36 +02:00
bool ignoreTmpExp = getFlag ( skillIndex , kDMIgnoreTemporaryExperience ) ;
bool ignoreObjModifiers = getFlag ( skillIndex , kDMIgnoreObjectModifiers ) ;
clearFlag ( skillIndex , kDMIgnoreTemporaryExperience | kDMIgnoreObjectModifiers ) ;
2016-08-23 07:54:16 +02:00
Champion * champ = & _champions [ champIndex ] ;
2016-08-26 22:51:17 +02:00
Skill * skill = & champ - > _skills [ skillIndex ] ;
int32 exp = skill - > _experience ;
if ( ! ignoreTmpExp )
exp + = skill - > _temporaryExperience ;
2016-09-09 07:32:32 +02:00
if ( skillIndex > kDMSkillWizard ) {
2016-08-26 22:51:17 +02:00
// Hidden skill
2016-09-09 07:32:32 +02:00
skill = & champ - > _skills [ ( skillIndex - kDMSkillSwing ) > > 2 ] ;
2016-08-26 22:51:17 +02:00
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 ) {
2016-09-10 11:47:36 +02:00
int16 actionHandIconIndex = _vm - > _objectMan - > getIconIndex ( champ - > _slots [ kDMSlotActionHand ] ) ;
2016-09-09 07:12:36 +02:00
if ( actionHandIconIndex = = kDMIconIndiceWeaponTheFirestaff )
2016-08-26 22:51:17 +02:00
skillLevel + + ;
2016-09-09 07:12:36 +02:00
else if ( actionHandIconIndex = = kDMIconIndiceWeaponTheFirestaffComplete )
2016-08-26 22:51:17 +02:00
skillLevel + = 2 ;
2016-09-10 11:47:36 +02:00
int16 neckIconIndex = _vm - > _objectMan - > getIconIndex ( champ - > _slots [ kDMSlotNeck ] ) ;
2016-08-26 22:51:17 +02:00
switch ( skillIndex ) {
2016-09-09 07:32:32 +02:00
case kDMSkillWizard :
2016-09-09 07:12:36 +02:00
if ( neckIconIndex = = kDMIconIndiceJunkPendantFeral )
2016-08-26 22:51:17 +02:00
skillLevel + = 1 ;
break ;
2016-09-09 07:32:32 +02:00
case kDMSkillHeal :
2016-08-26 22:51:17 +02:00
// The skill modifiers of these two objects are not cumulative
2016-09-09 07:12:36 +02:00
if ( ( neckIconIndex = = kDMIconIndiceJunkGemOfAges ) | | ( actionHandIconIndex = = kDMIconIndiceWeaponSceptreOfLyf ) )
2016-08-26 22:51:17 +02:00
skillLevel + = 1 ;
break ;
2016-09-09 07:32:32 +02:00
case kDMSkillInfluence :
2016-09-09 07:12:36 +02:00
if ( neckIconIndex = = kDMIconIndiceJunkMoonstone )
2016-08-26 22:51:17 +02:00
skillLevel + = 1 ;
break ;
2016-09-09 07:32:32 +02:00
case kDMSkillDefend :
2016-09-09 07:12:36 +02:00
if ( neckIconIndex = = kDMIconIndiceJunkEkkhardCross )
2016-08-26 22:51:17 +02:00
skillLevel + = 1 ;
break ;
default :
break ;
}
}
return skillLevel ;
}
}