Skip to content

Commit

Permalink
Merge pull request #452 from anatoliy-savchak/dev
Browse files Browse the repository at this point in the history
zmod introduction
  • Loading branch information
DudeMcDude authored Jan 3, 2021
2 parents c79dd5b + 8f40be5 commit 45f56b1
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 19 deletions.
1 change: 1 addition & 0 deletions TemplePlus/gamesystems/legacysystems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ SkillSystem::SkillSystem(const GameSystemConf &config) {
if (!startup(&config)) {
throw TempleException("Unable to initialize game system Skill");
}
skillSys.Init();
}
SkillSystem::~SkillSystem() {
auto shutdown = temple::GetPointer<void()>(0x1007d0c0);
Expand Down
73 changes: 70 additions & 3 deletions TemplePlus/inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "gamesystems/objects/objevent.h"
#include "ui/ui_logbook.h"
#include <config\config.h>

#include <mod_support.h>

InventorySystem inventory;

Expand Down Expand Up @@ -194,6 +194,14 @@ static class InventoryHooks : public TempleFix {
replaceFunction<int(__cdecl)(objHndl, objHndl)>(0x10066730, [](objHndl item, objHndl wielder){
return inventory.GetWeaponAnimId(item, wielder);
});

replaceFunction<int(__cdecl)(objHndl, objHndl, objHndl, SkillEnum)>(0x10069970, [](objHndl item, objHndl appraiser, objHndl vendor, SkillEnum skillEnum) {
return inventory.GetAppraisedWorth(item, appraiser, vendor, skillEnum);
});

replaceFunction<int(__cdecl)(objHndl, objHndl, objHndl, int)>(0x100698E0, [](objHndl item, objHndl parent, objHndl appraiser, int skillIdx) {
return inventory.GetAppraisedTransactionSum(item, parent, appraiser, (SkillEnum)skillIdx);
});
};


Expand Down Expand Up @@ -1353,10 +1361,69 @@ void InventorySystem::ItemPlaceInIdx(objHndl item, int idx)
TransferWithFlags(item, parent, idx, 4, objHndl::null);
}

int InventorySystem::IsTradeGoods(objHndl item)
{
auto type = objects.GetType(item);
auto cat = objects.getInt32(item, obj_f_category);
if (type == obj_t_generic && cat == 5) // jewelry / gems
return 1;
if (type == obj_t_armor && cat == 17) // stackable jewelry
return 1;
return 0;
}

int InventorySystem::GetAppraisedWorth(objHndl item, objHndl appraiser, objHndl vendor, SkillEnum skillEnum)
{
auto getAppraisedWorth = temple::GetRef<int(__cdecl)(objHndl, objHndl, objHndl, SkillEnum)>(0x10069970);
return getAppraisedWorth(item, appraiser, vendor, skillEnum);
auto skillLevelGet_1007D430 = temple::GetRef<double(__cdecl)(objHndl, int)>(0x1007D430);
auto skillLevel = skillLevelGet_1007D430(appraiser, skillEnum);
if (skillLevel > 19) skillLevel = 19;

double price = (double)GetSellWorth(item, appraiser, vendor, skillEnum);
if (!price)
return 0;

double result = ((double)skillLevel * 0.029999999 + 0.40000001) * price;

if (modSupport.IsZMOD()) {
if (IsTradeGoods(item)) {
return objects.getInt32(item, obj_f_item_worth);
}
auto getInvenSourceType = temple::GetRef<int(__cdecl)(objHndl)>(0x10064040);
auto invenSourceType = getInvenSourceType(vendor);

// if invenSourceType is not specified, then do not lower price
if (!invenSourceType) {
return (int)result;
}
}
auto getIsInVendorBuyList = temple::GetRef<int(__cdecl)(objHndl, objHndl)>(0x10066CD0);
auto isInVendorBuyList = getIsInVendorBuyList(item, vendor);
if (!isInVendorBuyList)
result = result * 0.5;
return (int)result;
}

int InventorySystem::GetAppraisedTransactionSum(objHndl item, objHndl parent, objHndl appraiser, SkillEnum skillEnum)
{
auto skillLevelGet_1007D430 = temple::GetRef<double(__cdecl)(objHndl, int)>(0x1007D430);
auto skillLevel = skillLevelGet_1007D430(appraiser, skillEnum);
if (skillLevel > 19) skillLevel = 19;

double price = (double)GetSellWorth(item, parent, appraiser, skillEnum);
if (!price)
return 0;

if (modSupport.IsZMOD()){
return (int)price;
}
double result = ((1.6 - (double)skillLevel * 0.029999999)) * price;
return (int)result;
}

int InventorySystem::GetSellWorth(objHndl item, objHndl appraiser, objHndl vendor, SkillEnum skillEnum)
{
auto getSellWorth = temple::GetRef<int(__cdecl)(objHndl, objHndl, objHndl, int)>(0x10067D20);
return getSellWorth(item, appraiser, vendor, skillEnum);
}

void InventorySystem::MoneyToCoins(int money, int* plat, int* gold, int* silver, int* copper)
Expand Down
3 changes: 3 additions & 0 deletions TemplePlus/inventory.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ struct InventorySystem : temple::AddressTable
/*
gets the item's sell price (in Copper Pieces) when dealing with a vendor
*/
int GetSellWorth(objHndl item, objHndl appraiser, objHndl vendor, SkillEnum skillEnum);
int GetAppraisedWorth(objHndl item, objHndl appraiser, objHndl vendor, SkillEnum skillEnum);
int GetAppraisedTransactionSum(objHndl item, objHndl parent, objHndl appraiser, SkillEnum skillEnum);
int IsTradeGoods(objHndl item);
void MoneyToCoins(int appraisedWorth, int* plat, int* gold, int* silver, int* copper);
int32_t GetCoinWorth(int32_t coinType);

Expand Down
20 changes: 20 additions & 0 deletions TemplePlus/mod_support.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ void ModSupport::DetectCo8ActiveModule(){
}
}

void ModSupport::DetectZMOD() {
mIsZMOD = false;
if (!config.defaultModule.empty() && (tolower(config.defaultModule).find("zmod") != std::string::npos))
{
mIsZMOD = true;
}
}

bool ModSupport::IsCo8NCEdition() const
{
if (!mInited)
Expand Down Expand Up @@ -101,6 +109,18 @@ bool ModSupport::IsCo8() const
return mIsCo8;
}

bool ModSupport::IsZMOD() const
{
if (!mInited)
throw TempleException("ModSupport uninited");
return mIsZMOD;
}

void ModSupport::SetIsZMOD(bool value)
{
mIsZMOD = value;
}

void ModSupport::SetNCGameFlag(bool value){
modSupportAddresses.Set(500, value);
}
4 changes: 4 additions & 0 deletions TemplePlus/mod_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ friend class TigInitializer;
bool IsKotB() const;
bool IsIWD() const;
bool IsCo8() const;
bool IsZMOD() const;
void SetIsZMOD(bool value);
static void SetNCGameFlag(bool value);
private:
void DetectCo8ActiveModule();
void DetectZMOD();
bool mIsCo8NC = false;
bool mIsKotB = false;
bool mIsIWD = false;
bool mIsCo8 = false;
bool mIsZMOD = false;
bool mInited = false;
};

Expand Down
14 changes: 12 additions & 2 deletions TemplePlus/python/python_dispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "history.h"
#include "bonus.h"
#include "config/config.h"
#include <mod_support.h>
#include "gamesystems/gamesystems.h"

namespace py = pybind11;
Expand Down Expand Up @@ -148,6 +149,9 @@ PYBIND11_EMBEDDED_MODULE(tpdp, m) {
else if (configItemLower == "hponlevelup") {
return config.hpOnLevelup;
}
else if (configItemLower == "defaultmodule") {
return config.defaultModule;
}

logger->warn("Can't get config item {}.", configItem);
return std::string("");
Expand All @@ -164,12 +168,15 @@ PYBIND11_EMBEDDED_MODULE(tpdp, m) {
else if (configItemLower == "disabletargetsurrounded") {
config.disableTargetSurrounded = value;
}
else if ("disablechooserandomspell_regardinvulnerablestatus") {
else if (configItemLower == "disablechooserandomspell_regardinvulnerablestatus") {
config.disableChooseRandomSpell_RegardInvulnerableStatus = value;
}
else if ("stricterrulesenforcement") {
else if (configItemLower == "stricterrulesenforcement") {
config.stricterRulesEnforcement = value;
}
else if (configItemLower == "iszmod") {
modSupport.SetIsZMOD(value);
}
else {
logger->warn("Can't set config item {}.", configItem);
}
Expand All @@ -192,6 +199,9 @@ PYBIND11_EMBEDDED_MODULE(tpdp, m) {
else if (configItemLower == "stricterrulesenforcement") {
return config.stricterRulesEnforcement;
}
else if (configItemLower == "iszmod") {
return modSupport.IsZMOD();
}
logger->warn("Can't get config item {}.", configItem);
return false;
});
Expand Down
36 changes: 23 additions & 13 deletions TemplePlus/python/python_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2441,23 +2441,33 @@ static PyObject* PyObjHandle_StandpointSet(PyObject* obj, PyObject* args) {
return PyInt_FromLong(0);
}
StandPointType type;
int jumpPointId;
if (!PyArg_ParseTuple(args, "ii:objhndl.standpoint_set", &type, &jumpPointId)) {
StandPoint standPoint;
standPoint.location = LocAndOffsets::null;
standPoint.location.off_x = 0;
standPoint.location.off_y = 0;
standPoint.mapId = 0;
standPoint.jumpPointId = -1;
if (!PyArg_ParseTuple(args, "ii|Liff:objhndl.standpoint_set", &type, &standPoint.jumpPointId, &standPoint.location.location, &standPoint.mapId, &standPoint.location.off_x, &standPoint.location.off_y)) {
return 0;
}

JumpPoint jumpPoint;
if (!maps.GetJumpPoint(jumpPointId, jumpPoint)) {
PyErr_Format(PyExc_ValueError, "Unknown jump point id %d used to set a standpoint.", jumpPointId);
return 0;
}
if (standPoint.jumpPointId >= 0) {
JumpPoint jumpPoint;
if (!maps.GetJumpPoint(standPoint.jumpPointId, jumpPoint)) {
PyErr_Format(PyExc_ValueError, "Unknown jump point id %d used to set a standpoint.", standPoint.jumpPointId);
return 0;
}

StandPoint standPoint;
standPoint.location.location = jumpPoint.location;
standPoint.location.off_x = 0;
standPoint.location.off_y = 0;
standPoint.mapId = jumpPoint.mapId;
standPoint.jumpPointId = jumpPointId;
standPoint.location.location = jumpPoint.location;
standPoint.location.off_x = 0;
standPoint.location.off_y = 0;
standPoint.mapId = jumpPoint.mapId;
}
else {
if (!standPoint.mapId) {
standPoint.mapId = maps.GetCurrentMapId();
}
}
critterSys.SetStandPoint(self->handle, type, standPoint);
Py_RETURN_NONE;
}
Expand Down
47 changes: 47 additions & 0 deletions TemplePlus/skill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "util/fixes.h"
#include "float_line.h"
#include "d20.h"
#include <infrastructure/json11.hpp>
#include <infrastructure/vfs.h>

#pragma region SkillSystem Implementation
LegacySkillSystem skillSys;
Expand Down Expand Up @@ -79,4 +81,49 @@ LegacySkillSystem::LegacySkillSystem(){
macRebase(skillPropsTable, 102CBA30)
}

void LegacySkillSystem::Init()
{
LoadSkillsProps("rules\\skills_props.json");
}

void LegacySkillSystem::LoadSkillsProps(const std::string& path)
{
std::string error;
if (!vfs->FileExists(path)) return;
json11::Json json = json.parse(vfs->ReadAsString(path), error);

if (json.is_null()) {
throw TempleException("Unable to parse skills_props.json from {}: {}", path, error);
}

if (!json.is_array()) {
throw TempleException("skills_props.json must start with an array at the root");
}

for (auto& item : json.array_items()) {
if (!item.is_object()) {
logger->warn("Skipping skill that is not an object.");
continue;
}
auto idNode = item["id"];
if (!idNode.is_number()) {
logger->warn("Skipping skill that is missing 'id' attribute.");
continue;
}
uint32_t id = (uint32_t)item["id"].int_value();
if (id < 0 || id >= SkillEnum::skill_count) {
logger->warn("Skipping skill that is out of bounds.");
continue;
}

if (!item["enabled"].is_number()) {
logger->warn("Skipping skill that is missing 'enabled' int attribute.");
continue;
}
uint32_t enabled = (uint32_t)item["enabled"].int_value();
if (enabled)
skillPropsTable[id].classFlags &= ~0x80000000;
else skillPropsTable[id].classFlags |= 0x80000000;
}
}
#pragma endregion
4 changes: 3 additions & 1 deletion TemplePlus/skill.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ struct LegacySkillSystem : temple::AddressTable {
Stat GetSkillStat(SkillEnum skillEnum);

LegacySkillSystem();


void LoadSkillsProps(const std::string& path);
void Init();
};

extern LegacySkillSystem skillSys;
Expand Down
1 change: 1 addition & 0 deletions TemplePlus/tig/tig_startup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ void TigInitializer::LoadDataFiles() {
else {
moduleBase = moduleName;
}
modSupport.DetectZMOD();

auto moduleCoreDatName = moduleBase + "_core.dat";
auto moduleDir = moduleBase + "_core";
Expand Down
25 changes: 25 additions & 0 deletions TemplePlus/ui/ui_char.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <combat.h>
#include "ui_item_creation.h"
#include <history.h>
#include "mod_support.h"

#include "condition.h"

Expand Down Expand Up @@ -1782,8 +1783,31 @@ void UiCharHooks::ItemGetDescrAddon(objHndl obj, objHndl item, std::string& addS
addStr = fmt::format("Remaining Charges: {}", remCharges);
}
}
if (modSupport.IsZMOD())
{
auto itemFlags = itemObj->GetItemFlags();
if (!(itemFlags & OIF_IS_MAGICAL) || (itemFlags & OIF_IDENTIFIED))
{
int worth = gameSystems->GetObj().GetObject(item)->GetInt32(obj_f_item_worth);
if (worth > 0) {
int plat = 0, gold = 0, silver = 0, copper = 0;
inventory.MoneyToCoins(worth, &plat, &gold, &silver, &copper);
gold += plat * 10;
addStr = fmt::format((addStr.length() > 0) ? "{0}\nPrice: {1}" : "Price: {1}{2}{3}"
, addStr
, (gold || (!silver && !copper)) ? fmt::format("{0} gp ", gold) : ""
, (silver) ? fmt::format("{0} sp ", silver) : ""
, (copper) ? fmt::format("{0} cp ", copper) : ""
);
}
}
else {
addStr = fmt::format((addStr.length() > 0) ? "{0}\nPrice: Unidentified" : "Price: Unidentified", addStr);
}
}
}


void UiCharHooks::LongDescriptionPopupCreate(objHndl item)
{
auto &popupHandler = uiSystems->GetPopup();
Expand Down Expand Up @@ -2580,6 +2604,7 @@ bool UiCharImpl::SkillsBtnMsg(int widId, TigMsg& msg)
int scrollbarY = 0;
uiManager->ScrollbarGetY(skillsScrollbar->widgetId, &scrollbarY);
auto skillIdx = scrollbarY + widIdx;

if (skillIdx >= 0 && static_cast<size_t>(skillIdx) < skillsMap.size()) {
auto skillEnum = skillsMap[skillIdx];
auto handle = ui_char().GetCritter();
Expand Down

0 comments on commit 45f56b1

Please sign in to comment.