// restores the real dude state static void RestoreRealDudeState() { *ptr_obj_dude = real_dude; *ptr_inven_dude = real_dude; *ptr_itemCurrentItem = real_hand; memcpy(ptr_itemButtonItems, real_itemButtonItems, sizeof(DWORD) * 6 * 2); memcpy(ptr_pc_traits, real_traits, sizeof(DWORD) * 2); memcpy(*ptr_perkLevelDataList, real_perkLevelDataList, sizeof(DWORD) * PERK_count); strcpy_s(ptr_pc_name, 32, real_pc_name); *ptr_Level_ = real_Level; *ptr_last_level = real_last_level; *ptr_Experience_ = real_Experience; *ptr_free_perk = real_free_perk; ptr_curr_pc_stat[0] = real_unspent_skill_points; //real_map_elevation = *ptr_map_elevation; -- why save elevation? *ptr_sneak_working = real_sneak_working; SkillSetTags(real_tag_skill, 4); *ptr_inven_pid = real_dude->pid; if (DelayedExperience > 0) { StatPcAddExperience(DelayedExperience); } InterfaceRedraw(); SetInventoryCheck(false); IsControllingNPC = 0; real_dude = nullptr; }
// take control of the NPC static void TakeControlOfNPC(TGameObj* npc) { // remove skill tags int tagSkill[4]; #if (_MSC_VER < 1600) std::fill(std_begin(tagSkill), std_end(tagSkill), -1); #else std::fill(std::begin(tagSkill), std::end(tagSkill), -1); #endif SkillSetTags(tagSkill, 4); // reset traits ptr_pc_traits[0] = ptr_pc_traits[1] = -1; // reset perks for (int i = 0; i < PERK_count; i++) { (*ptr_perkLevelDataList)[i] = 0; } // change character name CritterPcSetName(CritterName(npc)); // change level int level = IsPartyMember(npc) ? PartyMemberGetCurrentLevel(npc) : 0; *ptr_Level_ = level; *ptr_last_level = level; // reset other stats *ptr_Experience_ = 0; *ptr_free_perk = 0; ptr_curr_pc_stat[0] = 0; *ptr_sneak_working = 0; // deduce active hand by weapon anim code char critterAnim = (npc->artFID & 0xF000) >> 12; // current weapon as seen in hands if (AnimCodeByWeapon(GetInvenWeaponLeft(npc)) == critterAnim) { // definitely left hand.. *ptr_itemCurrentItem = 0; } else { *ptr_itemCurrentItem = 1; } *ptr_inven_pid = npc->pid; // switch main dude_obj pointers - this should be done last! *ptr_obj_dude = npc; *ptr_inven_dude = npc; IsControllingNPC = 1; DelayedExperience = 0; SetInventoryCheck(true); InterfaceRedraw(); }
// return values: 0 - use vanilla handler, 1 - skip vanilla handler, return 0 (normal status), -1 - skip vanilla, return -1 (game ended) static int _stdcall CombatWrapperInner(TGameObj* obj) { if ((obj != *obj_dude_ptr) && (Chars.size() == 0 || IsInPidList(obj)) && (Mode == 1 || IsPartyMember(obj))) { IsControllingNPC = 1; SetInventoryCheck(true); char dudeWeaponSlot = (char)*activeUIHand_ptr; // save "real" dude state real_dude = *obj_dude_ptr; *obj_dude_ptr = obj; *inven_dude_ptr = obj; memcpy(real_traits, dude_traits, sizeof(DWORD)*2); // deduce active hand by weapon anim code char critterAnim = (obj->artFID & 0xF000) >> 12; // current weapon as seen in hands if (AnimCodeByWeapon(GetInvenWeaponLeft(obj)) == critterAnim) { // definitely left hand.. *activeUIHand_ptr = 0; } else { *activeUIHand_ptr = 1; } int turnResult; __asm { call intface_redraw_; mov eax, obj; call combat_turn_; mov turnResult, eax; } // restore state if (IsControllingNPC) { // if game was loaded during turn, PartyControlReset() was called and already restored state *activeUIHand_ptr = dudeWeaponSlot; memcpy(dude_traits, real_traits, sizeof(DWORD)*2); *obj_dude_ptr = real_dude; *inven_dude_ptr = real_dude; __asm { call intface_redraw_; } SetInventoryCheck(false); IsControllingNPC = 0; } // -1 means that combat ended during turn return (turnResult == -1) ? -1 : 1; }