view Party.cpp @ 1178:f7ad7bd0a806

Слияние
author Ritor1
date Tue, 04 Jun 2013 09:44:53 +0600
parents 29a8defbad9e
children 15ad868d972f
line wrap: on
line source

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <assert.h>

#include "Party.h"
#include "MapInfo.h"
#include "Time.h"
#include "AudioPlayer.h"
#include "IconFrameTable.h"
#include "Mouse.h"
#include "PlayerFrameTable.h"
#include "TurnEngine.h"
#include "Viewport.h"
#include "Actor.h"
#include "GUIWindow.h"
#include "texts.h"

#include "mm7_data.h"
#include "MM7.h"







Party *pParty; // idb

struct ActionQueue *pPartyActionQueue = new ActionQueue;





//----- (0044A56A) --------------------------------------------------------
void Party::CountHirelings()
{
  field_70A = 0;

  for (int i = 0; i < pNPCStats->uNumNewNPCs; ++i)
  {
    auto npc = pNPCStats->pNewNPCData + i;
    if (npc->Hired() &&
        (!pHirelings[0].pName || strcmp(npc->pName, pHirelings[0].pName)))
    {
      if (!pHirelings[1].pName || strcmp(npc->pName, pHirelings[1].pName))
        ++field_70A;
    }
  }
}


// inlined
//----- (mm6c::004858D0) --------------------------------------------------
void Party::Zero()
{
  
  uFlags2 = 0;
  uNumGoldInBank = 0;

    uCurrentYear = 0;
    uCurrentMonth = 0;
    uCurrentMonthWeek = 0;
    uDaysPlayed = 0;
    uCurrentHour = 0;
    uCurrentMinute = 0;
    uCurrentTimeSecond = 0;

    field_6FC = 0;
    days_played_without_rest = 0;

    vPosition.y = 0;
    vPosition.z = 0;
    vPosition.x = 0;
    uFallStartY = 0;
    sRotationY = 0;
    sRotationX = 0;
    uFallSpeed = 0;
    field_28 = 0;
    uDefaultPartyHeight = 120;
    field_14 = 37;
    y_rotation_granularity = 25;
    uWalkSpeed = 384;
    y_rotation_speed = 90;
    field_24 = 5;
    field_6FC = 0;
    field_708 = 15;
    field_0 = 25;
}

//inlined
//----- (mm6c::0045BE90) --------------------------------------------------
void ActionQueue::Reset()
{
  uNumActions = 0;
}

//----- (004760C1) --------------------------------------------------------
void ActionQueue::Add(PartyAction action)
{
  if (uNumActions < 30)
    pActions[uNumActions++] = action;
}

//----- (00497FC5) --------------------------------------------------------
bool Party::_497FC5_check_party_perception_against_level()
{
  int uMaxPerception; // edi@1
  Player *v2; // esi@1
  signed int v3; // ebx@1
  Player *v4; // ecx@2
  signed int v5; // eax@3
  bool result; // eax@7

  uMaxPerception = 0;
  v2 = this->pPlayers;
  v3 = 4;
  do
  {
    if ( v2->CanAct() )
    {
      v5 = v2->GetPerception();
      if ( v5 > uMaxPerception )
        uMaxPerception = v5;
    }
    ++v2;
    --v3;
  }
  while ( v3 );
  if ( uLevelMapStatsID && (signed int)uLevelMapStatsID < 77 )
    result = uMaxPerception >= 2 * pMapStats->pInfos[uLevelMapStatsID]._per;
  else
    result = 0;
  return result;
}

//----- (004936E1) --------------------------------------------------------
void Party::SetHoldingItem(ItemGen *pItem)
{
  sub_421B2C_PlaceInInventory_or_DropPickedItem();
  memcpy(&pPickedItem, pItem, sizeof(pPickedItem));
  pMouse->SetCursorBitmapFromItemID(pPickedItem.uItemID);
}

//----- (0049370F) --------------------------------------------------------
int Party::GetNextActiveCharacter()
{
  Party *v1; // esi@1
  int v2; // eax@4
  signed int v4; // ecx@6
  Player *v5; // edx@6
  Player *v6; // eax@7
  Player *v7; // ecx@23
  signed int v8; // esi@23
  signed int v9; // edx@23
  Player **v10; // edi@23
  Player *v11; // eax@24
  int v12; // [sp+Ch] [bp-4h]@1

  v1 = this;
  v12 = 0;
  if ( pParty->bTurnBasedModeOn == 1 )
  {
    if ( pTurnEngine->field_4 != 2 || PID_TYPE(pTurnEngine->pQueue[0].uPackedID) != OBJECT_Player)
      return 0;
    v2 = PID_ID(pTurnEngine->pQueue[0].uPackedID);
    return v2 + 1;
  }
  v4 = 0;
  v5 = v1->pPlayers;//[0].uTimeToRecovery;
  while ( 1 )
  {
    v6 = ::pPlayers[v4 + 1];
    if ( v6->pConditions[2]
      || v6->pConditions[12]
      || v6->pConditions[13]
      || v6->pConditions[14]
      || v6->pConditions[15]
      || v6->pConditions[16]
	  || v5->uTimeToRecovery )
    {
      byte_AE3368[v4] = 1;
    }
    else if ( !byte_AE3368[v4] )
      break;
    ++v4;
    ++v5;
    if ( v4 >= 4 )
      break;
  }
  if(v4<4)
  {
	  v12 = v4;
	  byte_AE3368[v4] = 1;
  }
  if ( (unsigned __int8)(byte_AE3369 & byte_AE336A & byte_AE336B) & byte_AE3368[0] )
    memset(byte_AE3368, 0, 4u);
  v2 = v12;
  if ( v12 )
    return v2 + 1;
  v7 = v1->pPlayers;//[0].uSpeedBonus;
  v8 = 0;
  v9 = 1;
  v10 = &::pPlayers[1];
  while ( 2 )
  {
    v11 = *v10;
    if ( !(*v10)->pConditions[2]
      && !v11->pConditions[12]
      && !v11->pConditions[13]
      && !v11->pConditions[14]
      && !v11->pConditions[15]
      && !v11->pConditions[16]
	  && !v7->uTimeToRecovery )
    {
      if ( v12 )
      {
		if ( v7->uSpeedBonus > v8 )
        {
          v8 = v7->uSpeedBonus;
          v12 = v9;
        }
      }
      else
      {
        v8 = *(short *)v7;
        v12 = v9;
      }
    }
    ++v10;
    ++v9;
    ++v7;
    if ( v9 - 1 < 4 )
      continue;
    return v12;
  }
}


//----- (00493244) --------------------------------------------------------
bool Party::HasItem(unsigned int uItemID)
{
  Player *v2; // edx@1
  signed int v3; // ecx@2
  ItemGen *v4; // eax@2

  v2 = pParty->pPlayers;//[0].pInventoryItems;
  while ( v2 <= &pParty->pPlayers[3] )
  {
    v3 = 0;
	v4 = v2->pInventoryItems;
    do
    {
      if ( v4->uItemID == uItemID )
        return 1;
      ++v3;
      ++v4;
    }
    while ( v3 < 138 );
    ++v2;
  }
  return 0;
}


//----- (00492AD5) --------------------------------------------------------
void Party::SetFood(unsigned int uNumFood)
{
  pUIAnim_Food->uAnimTime = 0;
  pParty->uNumFoodRations = uNumFood;
  pUIAnim_Food->uAnimLength = 8 * pIconsFrameTable->pIcons[pUIAnim_Food->uIconID].uAnimLength;
}

//----- (00492B03) --------------------------------------------------------
void Party::TakeFood(unsigned int uNumFood)
{
  if (pParty->uNumFoodRations <= uNumFood)
    pParty->uNumFoodRations = 0;
  else
    pParty->uNumFoodRations -= uNumFood;

  pUIAnim_Food->uAnimTime = 0;
  pUIAnim_Food->uAnimLength = 8 * pIconsFrameTable->pIcons[pUIAnim_Food->uIconID].uAnimLength;
}

//----- (00492B42) --------------------------------------------------------
void Party::GiveFood(unsigned int _this)
{
  pParty->uNumFoodRations += _this;
  pUIAnim_Food->uAnimTime = 0;
  pUIAnim_Food->uAnimLength = 8 * pIconsFrameTable->pIcons[pUIAnim_Food->uIconID].uAnimLength;
}

//----- (00492B70) --------------------------------------------------------
void Party::SetGold(unsigned int uNumGold)
{
  pParty->uNumGold = uNumGold;
  pUIAnim_Gold->uAnimTime = 0;
  pUIAnim_Gold->uAnimLength = 8 * pIconsFrameTable->pIcons[pUIAnim_Gold->uIconID].uAnimLength;
  pAudioPlayer->PlaySound(SOUND_GoldReceived, 0, 0, -1, 0, 0, 0, 0);
}

//----- (00492BB6) --------------------------------------------------------
void Party::TakeGold(unsigned int uNumGold)
{
  if ( uNumGold <= pParty->uNumGold )
    pParty->uNumGold -= uNumGold;
  else
    pParty->uNumGold = 0;
  pUIAnim_Gold->uAnimTime = 0;
  pUIAnim_Gold->uAnimLength = 8 * pIconsFrameTable->pIcons[pUIAnim_Gold->uIconID].uAnimLength;
  pAudioPlayer->PlaySound(SOUND_GoldReceived, 0, 0, -1, 0, 0, 0, 0);
}

//----- (0049135E) --------------------------------------------------------
unsigned int Party::GetPartyFame()
{
  unsigned __int64 total_exp = 0;
  for (uint i = 0; i < 4; ++i)
    total_exp += pPlayers[i].uExperience;
  return total_exp / 1000;
}

//----- (0049137D) --------------------------------------------------------
void Party::CreateDefaultParty(char bGiveItems)
{
  Party *pParty; // esi@1
  signed __int16 v3; // ax@1
  //int pResMagicBase; // ecx@1
  Player *pCharacter; // esi@3
  //signed int uSpellBookPageCount; // edx@5
  int pMagicSkills; // eax@5
  int uSkillIdx; // eax@11
  //unsigned __int8 v9; // zf@37
  //char v10; // sf@37
  //unsigned __int8 v11; // of@37
  ItemGen *pItems; // eax@38
  signed int v13; // ecx@38
  int uMaxSP; // eax@42
  unsigned int v15; // [sp-4h] [bp-44h]@14
  unsigned int v16; // [sp-4h] [bp-44h]@26
  int v17; // [sp+10h] [bp-30h]@1
  int v18; // [sp+14h] [bp-2Ch]@11
  signed int uNumPlayers; // [sp+18h] [bp-28h]@1
  ItemGen Dst; // [sp+1Ch] [bp-24h]@10


  pParty = this;

  pHireling1Name[0] = 0;
  pHireling2Name[0] = 0;
  pParty->field_709 = 0;
  memset(pHirelings, 0, 2 * sizeof(*pHirelings));

  strcpy(this->pPlayers[0].pName, pGlobalTXT_LocalizationStrings[509]); //Zoltan
  pParty->pPlayers[0].uPrevFace = 17;
  pParty->pPlayers[0].uCurrentFace = 17;
  pParty->pPlayers[0].uPrevVoiceID = 17;
  pParty->pPlayers[0].uVoiceID = 17;
  pParty->pPlayers[0].uMight = 30;
  pParty->pPlayers[0].uIntelligence = 5;
  pParty->pPlayers[0].uWillpower = 5;
  pParty->pPlayers[0].uEndurance = 13;
  pParty->pPlayers[0].uAccuracy = 13;
  pParty->pPlayers[0].uSpeed = 14;
  pParty->pPlayers[0].uLuck = 7;
  pParty->pPlayers[0].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;         // leather
  pParty->pPlayers[0].pActiveSkills[PLAYER_SKILL_ARMSMASTER] = 1;        // armsmaster
  pParty->pPlayers[0].pActiveSkills[PLAYER_SKILL_BOW] = 1;         // bow
  pParty->pPlayers[0].pActiveSkills[PLAYER_SKILL_SWORD] = 1;         // sword
  pParty->pPlayers[1].uPrevFace = 3;
  pParty->pPlayers[1].uCurrentFace = 3;
  pParty->pPlayers[1].uPrevVoiceID = 3;
  pParty->pPlayers[1].uVoiceID = 3;
  strcpy(pParty->pPlayers[1].pName, pGlobalTXT_LocalizationStrings[506]); //Roderic
  pParty->pPlayers[1].uMight = 13;
  pParty->pPlayers[1].uIntelligence = 9;
  pParty->pPlayers[1].uWillpower = 9;
  pParty->pPlayers[1].uEndurance = 13;
  pParty->pPlayers[1].uAccuracy = 13;
  pParty->pPlayers[1].uSpeed = 13;
  pParty->pPlayers[1].uLuck = 13;
  pParty->pPlayers[1].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;         // leather
  pParty->pPlayers[1].pActiveSkills[PLAYER_SKILL_STEALING] = 1;        // stealing
  pParty->pPlayers[1].pActiveSkills[PLAYER_SKILL_DAGGER] = 1;         // dagger
  pParty->pPlayers[1].pActiveSkills[PLAYER_SKILL_TRAP_DISARM] = 1;        // disarm trap
  pParty->pPlayers[2].uPrevFace = 14;
  pParty->pPlayers[2].uCurrentFace = 14;
  pParty->pPlayers[2].uPrevVoiceID = 14;
  pParty->pPlayers[2].uVoiceID = 14;
  strcpy(pParty->pPlayers[2].pName, pGlobalTXT_LocalizationStrings[508]); // Serena
  pParty->pPlayers[2].uMight = 12;
  pParty->pPlayers[2].uIntelligence = 9;
  pParty->pPlayers[2].uWillpower = 20;
  pParty->pPlayers[2].uEndurance = 22;
  pParty->pPlayers[2].uAccuracy = 7;
  pParty->pPlayers[2].uSpeed = 13;
  pParty->pPlayers[2].uLuck = 7;
  pParty->pPlayers[2].pActiveSkills[PLAYER_SKILL_ALCHEMY] = 1;        // alchemy
  pParty->pPlayers[2].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;         // leather
  pParty->pPlayers[2].pActiveSkills[PLAYER_SKILL_BODY] = 1;        // body
  pParty->pPlayers[2].pActiveSkills[PLAYER_SKILL_MACE] = 1;         // mace
  strcpy(pParty->pPlayers[3].pName, pGlobalTXT_LocalizationStrings[507]); // Alexis
  v3 = 10;
  pParty->pPlayers[3].uPrevFace = 10;
  pParty->pPlayers[3].uCurrentFace = 10;
  //pResMagicBase = (int)&pParty->pPlayers[0].sResMagicBase;
  pParty->pPlayers[3].uEndurance = 13;
  pParty->pPlayers[3].uAccuracy = 13;
  pParty->pPlayers[3].uSpeed = 13;
  pParty->pPlayers[3].uPrevVoiceID = 10;
  pParty->pPlayers[3].uVoiceID = 10;
  pParty->pPlayers[3].uMight = 5;
  pParty->pPlayers[3].uIntelligence = 30;
  pParty->pPlayers[3].uWillpower = 9;
  pParty->pPlayers[3].uLuck = 7;
  pParty->pPlayers[3].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;         // leather
  pParty->pPlayers[3].pActiveSkills[PLAYER_SKILL_AIR] = 1;        // air
  pParty->pPlayers[3].pActiveSkills[PLAYER_SKILL_FIRE] = 1;        // fire
  pParty->pPlayers[3].pActiveSkills[PLAYER_SKILL_STAFF] = 1;         // staff
  //uNumPlayers = 4;
  //while ( 1 )
  for (uNumPlayers = 0; uNumPlayers < 4; uNumPlayers++)
  {
    pCharacter = &pParty->pPlayers[uNumPlayers];
    if (pCharacter->classType == PLAYER_CLASS_KNIGHT)
      pCharacter->sResMagicBase = v3; //player[i].pResMagicBase
    //uSpellBookPageCount = 0;
    //pMagicSkills = pPlayers[uNumPlayers].pActiveSkills[12];// Skills
    //while ( !*(short *)pMagicSkills )         //player[i].skillFire
    pCharacter->lastOpenedSpellbookPage = 0;
	for (int i = 0; i < 9; i++)//for Magic Book
    {
      //++uSpellBookPageCount;
      //pMagicSkills++;
      //if ( uSpellBookPageCount >= 9 )
        //goto LABEL_10;
	    if (pPlayers[uNumPlayers].pActiveSkills[12+i])
        {
          pCharacter->lastOpenedSpellbookPage = i;
          break;
        }
    }
//LABEL_10:
    pCharacter->uExpressionTimePassed = 0;
    Dst.Reset();
    if ( bGiveItems )
    {
      pItemsTable->GenerateItem(2, 40, &Dst); //ring
      pCharacter->AddItem2(-1, &Dst);
      //uSkillIdx = 0;
      //v18 = 0;
      //do
	  for (uSkillIdx = 0; uSkillIdx < 36; uSkillIdx++)
      {
        if ( pCharacter->pActiveSkills[uSkillIdx] )
        {
          switch ( uSkillIdx )
          {
            case PLAYER_SKILL_STAFF:
              v15 = ITEM_STAFF_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_SWORD:
              v15 = ITEM_LONGSWORD_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_DAGGER:
              v15 = ITEM_DAGGER_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_AXE:
              v15 = ITEM_AXE_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_SPEAR:
              v15 = ITEM_SPEAR_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_BOW:
              v15 = ITEM_CROSSBOW_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_MACE:
              v15 = ITEM_MACE_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_SHIELD:
              v15 = ITEM_BUCKLER_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_LEATHER:
              v15 = ITEM_LEATHER_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_CHAIN:
              v15 = ITEM_CHAINMAIL_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_PLATE:
              v15 = ITEM_PLATE_1;
              pCharacter->WearItem(v15);
              break;
            case PLAYER_SKILL_FIRE:
              v16 = ITEM_SPELLBOOK_FIRE_STRIKE;
              pCharacter->AddItem(-1, v16);
              break;
            case PLAYER_SKILL_AIR:
              v16 = ITEM_SPELLBOOK_AIR_FEATHER_FALL;
              pCharacter->AddItem(-1, v16);
              break;
            case PLAYER_SKILL_WATER:
              v16 = ITEM_SPELLBOOK_WATER_POISON_SPRAY;
              pCharacter->AddItem(-1, v16);
              break;
            case PLAYER_SKILL_EARTH:
              v16 = ITEM_SPELLBOOK_EARTH_SLOW;
              pCharacter->AddItem(-1, v16);
              break;
            case PLAYER_SKILL_SPIRIT:
              v16 = ITEM_SPELLBOOK_SPIRIT_BLESS;
              pCharacter->AddItem(-1, v16);
              break;
            case PLAYER_SKILL_MIND:
              v16 = ITEM_SPELLBOOK_MIND_MIND_BLAST;
              pCharacter->AddItem(-1, v16);
              break;
            case PLAYER_SKILL_BODY:
              v16 = ITEM_SPELLBOOK_BODY_FIRST_AID;
              pCharacter->AddItem(-1, v16);
              break;
            case PLAYER_SKILL_ITEM_ID:
            case PLAYER_SKILL_REPAIR:
            case PLAYER_SKILL_MEDITATION:
            case PLAYER_SKILL_PERCEPTION:
            case PLAYER_SKILL_DIPLOMACY:
            case PLAYER_SKILL_TRAP_DISARM:
            case PLAYER_SKILL_LEARNING:
              pCharacter->AddItem(-1, ITEM_POTION_BOTTLE);
              v16 = 5 * (rand() % 3 + 40);      // simple reagent
              pCharacter->AddItem(-1, v16);
              break;
            case PLAYER_SKILL_DODGE:
              v16 = ITEM_BOOTS_1;
              pCharacter->AddItem(-1, v16);
              break;
            case PLAYER_SKILL_UNARMED:
              v16 = ITEM_GAUNTLETS_1;
              pCharacter->AddItem(-1, v16);
              break;
            default:
              break;
          }
        }
        //uSkillIdx = v18 + 1;
        //v11 = uSkillIdx > 36;
        //v9 = v18 == 35;
        //v10 = uSkillIdx - 35 < 0;
      }
      //while (uSkillIdx < 36);
      pItems = pCharacter->pInventoryItems;
      //v13 = 138;
      for (int i = 0; i < 138; i++)
      {
		if ( pItems->uItemID )
          pItems->uAttributes |= 1;
        ++pItems;
        //--v13;
      }
      //while ( v13 );
    }
    pCharacter->sHealth = pCharacter->GetMaxHealth();
    pCharacter->sMana = pCharacter->GetMaxMana();
    //pCharacter++;
    //uNumPlayers--;
    //if (!uNumPlayers)
      //break;
    //pResMagicBase = (int)pCharacter;
    v3 = 10;
  }
}

//----- (004917CE) --------------------------------------------------------
int Party::Reset()
{
  //Party *v1; // esi@1
  //unsigned __int64 *pTimePlayed; // edi@1
  //bool v3; // edx@1
  //Player **v4; // eax@1
  //Player *v5; // ecx@1
  PLAYER_SEX pSex; // cl@3
  PLAYER_SEX v7; // al@6
  PLAYER_SEX v8; // al@9
  PLAYER_SEX v9; // cl@12
  //Player *v12; // edx@17
  //signed int v13; // edi@18
  SpellBuff *v14; // ebx@21
  signed int v15; // edi@21
  
  Zero();

  field_708 = 15;
  sEyelevel = 160;
  uNumGold = 200;
  uNumFoodRations = 7;

  
  alignment = PartyAlignment_Neutral;
  SetUserInterface(alignment, true);

  uTimePlayed = 0x21C00u;
  uLastRegenerationTime = 0x21C00;

  bTurnBasedModeOn = false;

  uActiveCharacter = 1;
  ::pPlayers[0] = pPlayers;
  for (uint i = 0; i < 4; ++i)
    ::pPlayers[i + 1] = &pPlayers[i];

  pPlayers[0].Reset(PLAYER_CLASS_KNIGHT);
  pPlayers[1].Reset(PLAYER_CLASS_THEIF);
  pPlayers[2].Reset(PLAYER_CLASS_CLERIC);
  pPlayers[3].Reset(PLAYER_CLASS_SORCERER);
  pPlayers[0].uCurrentFace = 17;
  pPlayers[0].uPrevVoiceID = 17;
  pPlayers[0].uVoiceID = 17;
  pPlayers[0].SetInitialStats();
 
  switch ( pPlayers[0].uVoiceID )
  {
    case 0:
    case 1:
    case 2:
    case 3:
    case 8:
    case 9:
    case 12:
    case 13:
    case 16:
    case 17:
    case 20:
    case 23:
    default:
      pSex = SEX_MALE;
      break;
    case 4:
    case 5:
    case 6:
    case 7:
    case 10:
    case 11:
    case 14:
    case 15:
    case 18:
    case 19:
    case 21:
    case 24:
      pSex = SEX_FEMALE;
      break;
  }
  pPlayers[0].uSex = pSex;
  pPlayers[0].RandomizeName();
  strcpy(pPlayers[0].pName, pGlobalTXT_LocalizationStrings[509]);


  pPlayers[1].uCurrentFace = 3;
  pPlayers[1].uPrevVoiceID = 3;
  pPlayers[1].uVoiceID = 3;
  pPlayers[1].SetInitialStats();
  v7 = SEX_MALE;
  switch (pPlayers[1].uVoiceID)
  {
    case 0:
    case 1:
    case 2:
    case 3:
    case 8:
    case 9:
    case 0xCu:
    case 0xDu:
    case 0x10u:
    case 0x11u:
    case 0x14u:
    case 0x17u:
      v7 = SEX_MALE;
      break;
    case 4:
    case 5:
    case 6:
    case 7:
    case 0xAu:
    case 0xBu:
    case 0xEu:
    case 0xFu:
    case 0x12u:
    case 0x13u:
    case 0x15u:
    case 0x18u:
      v7 = SEX_FEMALE;
      break;
    default:
      break;
  }
  pPlayers[1].uSex = v7;
  pPlayers[1].RandomizeName();
  strcpy(pPlayers[1].pName, pGlobalTXT_LocalizationStrings[506]);
  pPlayers[2].uCurrentFace = 14;
  pPlayers[2].uPrevVoiceID = 14;
  pPlayers[2].uVoiceID = 14;
  pPlayers[2].SetInitialStats();
  v8 = SEX_MALE;
  switch (pPlayers[2].uVoiceID)
  {
    case 0:
    case 1:
    case 2:
    case 3:
    case 8:
    case 9:
    case 0xCu:
    case 0xDu:
    case 0x10u:
    case 0x11u:
    case 0x14u:
    case 0x17u:
      v8 = SEX_MALE;
      break;
    case 4:
    case 5:
    case 6:
    case 7:
    case 0xAu:
    case 0xBu:
    case 0xEu:
    case 0xFu:
    case 0x12u:
    case 0x13u:
    case 0x15u:
    case 0x18u:
      v8 = SEX_FEMALE;
      break;
    default:
      break;
  }
  pPlayers[2].uSex = v8;
  pPlayers[2].RandomizeName();
  strcpy(pPlayers[2].pName, pGlobalTXT_LocalizationStrings[508]);
  pPlayers[3].uCurrentFace = 10;
  pPlayers[3].uPrevVoiceID = 10;
  pPlayers[3].uVoiceID = 10;
  pPlayers[3].SetInitialStats();
  v9 = SEX_MALE;
  switch (pPlayers[3].uVoiceID)
  {
    case 0u:
    case 1u:
    case 2u:
    case 3u:
    case 8u:
    case 9u:
    case 0xCu:
    case 0xDu:
    case 0x10u:
    case 0x11u:
    case 0x14u:
    case 0x17u:
      v9 = SEX_MALE;
      break;
    case 4u:
    case 5u:
    case 6u:
    case 7u:
    case 0xAu:
    case 0xBu:
    case 0xEu:
    case 0xFu:
    case 0x12u:
    case 0x13u:
    case 0x15u:
    case 0x18u:
      v9 = SEX_FEMALE;
      break;
    default:
      break;
  }
  pPlayers[3].uSex = v9;
  pPlayers[3].RandomizeName();
  strcpy(pPlayers[3].pName, pGlobalTXT_LocalizationStrings[507]);



  for (uint i = 0; i < 4; ++i)
  {
    pPlayers[i].uTimeToRecovery = 0;
    for (uint j = 0; j < 20; ++j)
      pPlayers[i].pConditions[j] = 0;

    for (uint j = 0; j < 24; ++j)
      pPlayers[i].pPlayerBuffs[j].Reset();

    pPlayers[i].expression = CHARACTER_EXPRESSION_1;
    pPlayers[i].uExpressionTimePassed = 0;
    pPlayers[i].uExpressionTimeLength = rand() % 256 + 128;
  }

  for (uint i = 1; i < 20; ++i)
    pPartyBuffs[i].Reset();


  pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 100;  // default character ui - stats
  uFlags = 0;
  memset(_autonote_bits, 0, 12);
  memset(_quest_bits, 0, 64);
  memset(pIsArtifactFound, 0, 29);
  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_RED_POTION_ACTIVE, 1);
  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_SEASHELL_ACTIVE, 1);
  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_LONGBOW_ACTIVE, 1);
  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_PLATE_ACTIVE, 1);
  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_LUTE_ACTIVE, 1);
  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_HAT_ACTIVE, 1);

  memset(field_3C._shop_ban_times,0,53*sizeof(__int64));

  memcpy(pNPCStats->pNewNPCData, pNPCStats->pNPCData, 0x94BCu);
  memcpy(pNPCStats->pGroups_copy, pNPCStats->pGroups, 0x66u);
  pNPCStats->pNewNPCData[3].uFlags |= 128;//|= 0x80u; Lady Margaret
  _494035_timed_effects__water_walking_damage__etc();
  pEventTimer->Pause();
  return 0;
}


//----- (0043AD34) --------------------------------------------------------
void Party::Yell()
{
  Actor *v0; // esi@5
  int v1; // edi@9
  int v2; // ebx@9
  int v3; // eax@9
  unsigned int v4; // [sp+8h] [bp-4h]@4

  if ( (signed __int64)pParty->pPartyBuffs[11].uExpireTime > 0 )
    pParty->pPartyBuffs[11].Reset();
  if ( pParty->bTurnBasedModeOn != 1 )
  {
    v4 = 0;
    if ( (signed int)uNumActors > 0 )
    {
      v0 = pActors;//[0].pMonsterInfo.uMovementType;
      do
      {
        if ( v0->Actor::CanAct() && v0->pMonsterInfo.uHostilityType != MonsterInfo::Hostility_Long && v0->pMonsterInfo.uMovementType != 5 )
        {
		  v1 = abs(v0->vPosition.x - pParty->vPosition.x);
		  v2 = abs(v0->vPosition.y - pParty->vPosition.y);
		  v3 = abs(v0->vPosition.z - pParty->vPosition.z);
          if (int_get_vector_length(v1, v2, v3) < 512)
            Actor::AI_Flee(v4, 4, 0, 0);
        }
        ++v4;
        ++v0;
      }
      while ( (signed int)v4 < (signed int)uNumActors );
    }
  }
}

//----- (00491BF9) --------------------------------------------------------
void Party::ResetPosMiscAndSpellBuffs()
{
  Party *v1; // esi@1
  Player *v2; // edi@1
  SpellBuff *v3; // ebx@2
  SpellBuff *v4; // esi@5
  signed int v5; // edi@5
  signed int v6; // [sp+8h] [bp-8h]@1
  signed int v7; // [sp+Ch] [bp-4h]@2

  v1 = this;
  this->vPosition.y = 0;
  this->vPosition.z = 0;
  this->vPosition.x = 0;
  this->uFallStartY = 0;
  this->sRotationY = 0;
  this->sRotationX = 0;
  this->uFallSpeed = 0;
  this->field_28 = 0;
  this->uDefaultPartyHeight = 120;
  this->field_14 = 37;
  this->y_rotation_granularity = 25;
  this->uWalkSpeed = 384;
  this->y_rotation_speed = 90;
  this->field_24 = 5;
  this->field_6FC = 0;
  this->field_708 = 15;
  this->field_0 = 25;
  v2 = this->pPlayers;//[0].pPlayerBuffs;
  v6 = 4;
  do
  {
    v3 = v2->pPlayerBuffs;
    v7 = 24;
    do
    {
      v3->Reset();
      ++v3;
      --v7;
    }
    while ( v7 );
    ++v2;
    --v6;
  }
  while ( v6 );
  v4 = v1->pPartyBuffs;
  v5 = 20;
  do
  {
    v4->Reset();
    ++v4;
    --v5;
  }
  while ( v5 );
}

//----- (004909F4) --------------------------------------------------------
void Party::UpdatePlayersAndHirelingsEmotions()
{
  //Player *v1; // esi@2
  //unsigned int v2; // eax@3
  //__int16 v3; // cx@5
  int v4; // edx@27
  //signed int v5; // eax@52
  //PlayerFrame *v6; // edx@53
  //NPCData *v7; // esi@60
  //signed int v8; // ebp@61
  //int v9; // ebx@62
  //unsigned int v10; // edi@62
  //signed int v11; // [sp+0h] [bp-4h]@2

  //v1 = this->pPlayers;//(char *)&this->pPlayers[0].uExpressionID;
  for (int i = 0; i < 4; ++i)
  {
    auto player = pPlayers + i;
    player->uExpressionTimePassed += (unsigned short)pMiscTimer->uTimeElapsed;


    auto condition = player->GetMajorConditionIdx();
    if (condition == Player::Condition_Good || condition == Player::Condition_Zombie)
    {
      if (player->uExpressionTimePassed < player->uExpressionTimeLength)
        continue;
        
      player->uExpressionTimePassed = 0;
      if (player->expression != 1 || rand() % 5)
      {
        player->expression = CHARACTER_EXPRESSION_1;
        player->uExpressionTimeLength = rand() % 256 + 32;
      }
      else
      {
        v4 = rand() % 100;
        if (v4 < 25)      player->expression = CHARACTER_EXPRESSION_13;
        else if (v4 < 31) player->expression = CHARACTER_EXPRESSION_14;
        else if (v4 < 37) player->expression = CHARACTER_EXPRESSION_15;
        else if (v4 < 43) player->expression = CHARACTER_EXPRESSION_16;
        else if (v4 < 46) player->expression = CHARACTER_EXPRESSION_17;
        else if (v4 < 52) player->expression = CHARACTER_EXPRESSION_18;
        else if (v4 < 58) player->expression = CHARACTER_EXPRESSION_19;
        else if (v4 < 64) player->expression = CHARACTER_EXPRESSION_20;
        else if (v4 < 70) player->expression = CHARACTER_EXPRESSION_54;
        else if (v4 < 76) player->expression = CHARACTER_EXPRESSION_55;
        else if (v4 < 82) player->expression = CHARACTER_EXPRESSION_56;
        else if (v4 < 88) player->expression = CHARACTER_EXPRESSION_57;
        else if (v4 < 94) player->expression = CHARACTER_EXPRESSION_29;
        else              player->expression = CHARACTER_EXPRESSION_30;
      }

      for (int j = 0; j < pPlayerFrameTable->uNumFrames; ++j)
      {
        auto frame = pPlayerFrameTable->pFrames + j;
        if (frame->expression == player->expression)
        {
          player->uExpressionTimeLength = 8 * pPlayerFrameTable->pFrames[j].uAnimLength;
          break;
        }
      }
    }
    else if (player->expression != 34 &&
             player->expression != 35 &&
             player->expression != 36 ||
             player->uExpressionTimePassed >= player->uExpressionTimeLength)
    {
      player->uExpressionTimeLength = 0;
      player->uExpressionTimePassed = 0;

      switch (condition)
      {
        case Player::Condition_Dead:        player->expression = CHARACTER_EXPRESSION_DEAD;      break;
        case Player::Condition_Pertified:   player->expression = CHARACTER_EXPRESSION_PERTIFIED; break;
        case Player::Condition_Eradicated:  player->expression = CHARACTER_EXPRESSION_ERADICATED; break;
        case Player::Condition_Cursed:      player->expression = CHARACTER_EXPRESSION_CURSED; break;
        case Player::Condition_Weak:        player->expression = CHARACTER_EXPRESSION_WEAK; break;
        case Player::Condition_Sleep:       player->expression = CHARACTER_EXPRESSION_SLEEP; break;
        case Player::Condition_Fear:        player->expression = CHARACTER_EXPRESSION_FEAR; break;
        case Player::Condition_Drunk:       player->expression = CHARACTER_EXPRESSION_DRUNK; break;
        case Player::Condition_Insane:      player->expression = CHARACTER_EXPRESSION_INSANE; break;
        case Player::Condition_Poison1:
        case Player::Condition_Poison2:
        case Player::Condition_Poison3:     player->expression = CHARACTER_EXPRESSION_POISONED; break;
        case Player::Condition_Disease1:
        case Player::Condition_Disease2:
        case Player::Condition_Disease3:    player->expression = CHARACTER_EXPRESSION_DISEASED; break;
        case Player::Condition_Paralyzed:   player->expression = CHARACTER_EXPRESSION_PARALYZED; break;
        case Player::Condition_Unconcious:  player->expression = CHARACTER_EXPRESSION_UNCONCIOUS; break;
        default:
          assert(false);
      }
    }
  }


  for (int i = 0; i < 2; ++i)
  {
    auto hireling = pParty->pHirelings + i;
    if (!hireling->evt_C)
      continue;

    hireling->evt_B += pMiscTimer->uTimeElapsed;
    if (hireling->evt_B >= hireling->evt_C)
    {
      hireling->evt_A = 0;
      hireling->evt_B = 0;
      hireling->evt_C = 0;

      assert(sizeof(NPCData) == 0x4C);
      memset(hireling, 0, sizeof(*hireling));

      pParty->field_709 = 0;
      pParty->CountHirelings();
      viewparams->bRedrawGameUI = true;
    }
  }
}

//----- (00490D02) --------------------------------------------------------
void Party::RestAndHeal()
{
  Player *pPlayer; // esi@4
  ItemGen *v7; // eax@10
  signed int v11; // ecx@26
  signed int v12; // [sp-4h] [bp-1Ch]@26
  bool have_vessels_soul; // [sp+10h] [bp-8h]@10

/*  v1 = pParty->pPartyBuffs;
  do
  {
    v1->Reset();
    ++v1;
  }
  while ( (signed int)v1 < (signed int)pParty->pPlayers );
  v15 = 0;
  do
  {
    pPlayer = &pParty->pPlayers[v15];
    v3 = 20;
    v4 = pPlayer->pPlayerBuffs;
    do
    {
      v4->Reset();
      ++v4;
      --v3;
    }
    while ( v3 );*/
  for ( uint i = 0; i < 20; ++i )
    pParty->pPartyBuffs[i].Reset();
  for ( int pPlayerID = 0; pPlayerID < 4; ++pPlayerID )
  {
    pPlayer = &pParty->pPlayers[pPlayerID];
    for ( uint i = 0; i < 20; ++i )
      pPlayer->pPlayerBuffs[i].Reset();

    pPlayer->Zero();
    if ( pPlayer->pConditions[14] || pPlayer->pConditions[15] || pPlayer->pConditions[16] )//Dead/Petrified/Eradicated
      continue;
    pPlayer->pConditions[13] = 0;//Unconcious
    pPlayer->pConditions[4] = 0;//Drunk
    pPlayer->pConditions[3] = 0;//Fear
    pPlayer->pConditions[2] = 0;//Sleep
    pPlayer->pConditions[1] = 0;//Weak
    pPlayer->uTimeToRecovery = 0;
    pPlayer->sHealth = pPlayer->GetMaxHealth();
    pPlayer->sMana = pPlayer->GetMaxMana();
    if ( pPlayer->classType == PLAYER_CLASS_LICH )
    {
      have_vessels_soul = false;
      v7 = pPlayer->pInventoryItems;//[0].field_1A;
      for ( uint i = 138; i; --i )
      {
        if ( v7->uItemID == 601 && (unsigned __int8)v7->uHolderPlayer == pPlayerID + 1 )
          have_vessels_soul = true;
        ++v7;
      }
      if ( !have_vessels_soul )
      {
        pPlayer->sHealth = pPlayer->GetMaxHealth() / 2;
        pPlayer->sMana = pPlayer->GetMaxMana() / 2;
      }
    }
    if ( !pPlayer->pConditions[17] )// Zombie
    {
      if ( pPlayer->pConditions[10] || pPlayer->pConditions[11] )
      {
        v11 = 4;
        v12 = 4;
      }
      else
      {
        if ( !pPlayer->pConditions[8] && !pPlayer->pConditions[9] )
        {
          if ( !pPlayer->pConditions[6] && !pPlayer->pConditions[7] )
          {
            if ( pPlayer->pConditions[5] )
              pPlayer->sMana = 0;
            UpdatePlayersAndHirelingsEmotions();
            continue;
          }
          pPlayer->sHealth /= 2;
          pPlayer->sMana = pPlayer->sMana / 2;
          if ( pPlayer->pConditions[5] )
            pPlayer->sMana = 0;
          UpdatePlayersAndHirelingsEmotions();
          continue;
        }
        v11 = 3;
        v12 = 3;
      }
      pPlayer->sHealth /= v11;
      pPlayer->sMana = pPlayer->sMana / v12;
      if ( pPlayer->pConditions[5] )
        pPlayer->sMana = 0;
      UpdatePlayersAndHirelingsEmotions();
      continue;
    }
    pPlayer->sMana = 0;
    pPlayer->sHealth = pPlayer->sHealth / 2;
    if ( pPlayer->pConditions[5] )
      pPlayer->sMana = 0;
    UpdatePlayersAndHirelingsEmotions();
  }
  pParty->days_played_without_rest = 0;
}