Думаю, нет надобности объяснять актуальность данной проблемы. В теме по скриптингу уже обсуждалось возможность динамического управления соотношением цен с помощью пакета Ikarus, написанного Sektenspinner-ом, однако была небольшая проблема - из-за специфики работы с памятью функций пакета, компиляция готиксорсером была невозможна, что усложняло реализацию для ленивых скриптеров вроде меня. Вчера лазя по польскому форуму themodders.org я наткнулся на упоминание первой версии Икаруса переделанной под Г1 orcwarrior-ом, и, о чудо, в отличие от последних версий там используются функции работы с памятью, не оптимизированные под движок с полным пренебрежением правил языка и готиксорсер работает с ними отлично. Сам пакет можно найти на немецком воге, но для данной цели нам надо только класс двига игры oCNpc (код его приводить не буду) и несколько функций, а именно: чтение и запись из памяти/в память из Икаруса и установка множителей для цен, написанная orcwarrior-ом.
Можно просто вставить в проект уже готовый файл: OCNPC18M.rar (не забудьте вписать его в .src файл поближе к началу).
Что важно: специфика работы с памятью требует задачу переменных типа float в виде int. Благо, добрый orcwarrior описал процедуру языком, понятным даже чайникам вроде меня: переводим например здесь http://babbage.cs.qc.cuny.edu/IEEE-754/Decimal.html наш float в 32-х битное шестнадцатеричное, а его виндозным калькулятором в десятиричное представление (халява в общем).
Теперь можно приступить к использованию функций. Для примера то, что я тестировал: вставляем в функцию ZS_Talk:
На выходе получаем: торговцы своего лагеря при принятии в призраки/воры/послушники будут свои товары отдавать в полтора раза дороже, а принимать за 30% стоимости. При последующем продвижении - продавать по реальной цене, а скупать за 40%. Для не самых дружественных Старого и Нового, при принадлежности к противоположному лагерю цена продажи вырастет до 3-х, а покупки упадет до 15%. В остальных случаях покупка за удвоенную цену, а продажа за 20%. Важно не забыть следующее: при коэффициенте покупки менее 50% руда будет приниматься торговцами за 0, так что желательно ее удорожить или использовать другое соотношение цен.
Код:
const int MEM_NpcID_Offset = 256; //0x100 const int MEMINT_oCInformationManager_Address = 10328072;//0x9D9808 //TODO: To everyone, in G1 there isn't universal hided wp like "TOT" in G2 //So You need to add some WP to all your worlds in hidden place and call them //the same const string MEM_FARFARAWAY = "GAME_START"; const string MEM_HELPER_NAME = "MEMHLP"; INSTANCE MEM_HELPER_INST (C_NPC) { name = MEM_HELPER_NAME; id = 42; flags = NPC_FLAG_IMMORTAL; attribute [ATR_HITPOINTS_MAX] = 2; attribute [ATR_HITPOINTS] = 2; Mdl_SetVisual (self, "meatbug.mds"); }; //###################################################### // // Elementare Read-Write Operationen // //###################################################### var oCNpc MEM_Helper; var C_NPC MEM_oldOth; //other hier zwischenspeichern func void MEMINT_GetMemHelper() { MEM_Helper = Hlp_GetNpc (MEM_HELPER_INST); if (!Hlp_IsValidNpc (MEM_Helper)) { //self zwischenspeichern MEM_oldOth = Hlp_GetNpc (self); Wld_InsertNpc (MEM_HELPER_INST, MEM_FARFARAWAY); MEM_Helper = Hlp_GetNpc (self); self = Hlp_GetNpc (MEM_oldOth); }; }; var int MEMINT_OpenCount; func void MEMINT_ReadOpen() { if (!MEMINT_OpenCount) { MEMINT_GetMemHelper(); MEM_oldOth = Hlp_GetNpc (other); }; MEMINT_OpenCount += 1; }; func void MEMINT_ReadClose() { MEMINT_OpenCount -= 1; if (!MEMINT_OpenCount) { MEM_Helper.enemy = 0; other = Hlp_GetNpc (MEM_oldOth); }; }; //Requires: Open, Close func int MEMINT_ReadInt (var int address) { // other = address - MEM_NpcID_Offset MEM_Helper.enemy = address - MEM_NpcID_Offset; // res wird nicht gebraucht, mьllt aber sonst den Stack zu! var int res; res = Npc_GetTarget (MEM_Helper); // res = *(other + oCNpc_idx_offset) return other.id; }; //Requires: Open, Close func void MEMINT_WriteInt (var int address, var int val) { // other = address - MEM_NpcID_Offset MEM_Helper.enemy = address - MEM_NpcID_Offset; // res wird nicht gebraucht, mьllt aber sonst den Stack zu! var int res; res = Npc_GetTarget (MEM_Helper); // (other + oCNpc_idx_offset) = val other.id = val; }; func int MEM_ReadInt (var int address) { var int res; MEMINT_ReadOpen(); res = MEMINT_ReadInt (address); MEMINT_ReadClose(); return res; }; func void MEM_WriteInt (var int address, var int val) { MEMINT_ReadOpen(); MEMINT_WriteInt (address, val); MEMINT_ReadClose(); }; //================================================== // Trade_ChangeSellMultiplier // ---- // - mul have to be zfloat value // - function should be refreshed atleast every trade // for simplify you can add it in ZS_TALK //================================================== func void Trade_ChangeSellMultiplier(var int mul) { var int ptr; ptr = MEMINT_oCInformationManager_Address; ptr = MEM_ReadInt(ptr+24);//oCInformationManager.dlgTrade ptr = MEM_ReadInt(ptr+260); //dlgTrade.oCViewDialogItemContainer MEM_WriteInt(ptr+268,mul);//oCViewDialogItemContainer.Multiplier = mul }; //================================================== // Trade_ChangeBuyMultiplier // ---- // - mul have to be zfloat value // - function should be refreshed atleast every trade // for simplify you can add it in ZS_TALK //================================================== func void Trade_ChangeBuyMultiplier(var int mul) { var int ptr; ptr = MEMINT_oCInformationManager_Address; ptr = MEM_ReadInt(ptr+24);//oCInformationManager.dlgTrade ptr = MEM_ReadInt(ptr+252); //dlgTrade.oCViewDialogStealContainer MEM_WriteInt(ptr+268,mul);//oCViewDialogStealContainer.Multiplier = mul };
Что важно: специфика работы с памятью требует задачу переменных типа float в виде int. Благо, добрый orcwarrior описал процедуру языком, понятным даже чайникам вроде меня: переводим например здесь http://babbage.cs.qc.cuny.edu/IEEE-754/Decimal.html наш float в 32-х битное шестнадцатеричное, а его виндозным калькулятором в десятиричное представление (халява в общем).
Теперь можно приступить к использованию функций. Для примера то, что я тестировал: вставляем в функцию ZS_Talk:
Код:
if (Npc_GetTrueGuild(self) == GIL_ORG || Npc_GetTrueGuild(self) == GIL_SLD || Npc_GetTrueGuild(self) == GIL_KDW) { if (Npc_GetTrueGuild(hero) == GIL_ORG) { Trade_ChangeBuyMultiplier (1069547520); // 1.5 Trade_ChangeSellMultiplier (1050253721); // 0.3 } else if (Npc_GetTrueGuild(hero) == GIL_SLD || Npc_GetTrueGuild(hero) == GIL_KDW) { Trade_ChangeBuyMultiplier (1065353216); // 1.0 Trade_ChangeSellMultiplier (1053609164); // 0.4 } else if (Npc_GetTrueGuild(hero) == GIL_STT || Npc_GetTrueGuild(hero) == GIL_GRD || Npc_GetTrueGuild(hero) == GIL_KDF) { Trade_ChangeBuyMultiplier (1077936128); // 3.0 Trade_ChangeSellMultiplier (1041865113); // 0.15 } else { Trade_ChangeBuyMultiplier (1073741824); // 2.0 Trade_ChangeSellMultiplier (1045220556); // 0.2 }; }; if (Npc_GetTrueGuild(self) == GIL_NOV || Npc_GetTrueGuild(self) == GIL_TPL || Npc_GetTrueGuild(self) == GIL_GUR) { if (Npc_GetTrueGuild(hero) == GIL_NOV) { Trade_ChangeBuyMultiplier (1069547520); // 1.5 Trade_ChangeSellMultiplier (1050253721); // 0.3 } else if (Npc_GetTrueGuild(hero) == GIL_TPL || Npc_GetTrueGuild(hero) == GIL_GUR) { Trade_ChangeBuyMultiplier (1065353216); // 1.0 Trade_ChangeSellMultiplier (1053609164); // 0.4 } else { Trade_ChangeBuyMultiplier (1073741824); // 2.0 Trade_ChangeSellMultiplier (1045220556); // 0.2 }; }; if (Npc_GetTrueGuild(self) == GIL_STT || Npc_GetTrueGuild(self) == GIL_GRD || Npc_GetTrueGuild(self) == GIL_KDF) { if (Npc_GetTrueGuild(hero) == GIL_STT) { Trade_ChangeBuyMultiplier (1069547520); // 1.5 Trade_ChangeSellMultiplier (1050253721); // 0.3 } else if (Npc_GetTrueGuild(hero) == GIL_GRD || Npc_GetTrueGuild(hero) == GIL_KDF) { Trade_ChangeBuyMultiplier (1065353216); // 1.0 Trade_ChangeSellMultiplier (1053609164); // 0.4 } else if (Npc_GetTrueGuild(hero) == GIL_ORG || Npc_GetTrueGuild(hero) == GIL_SLD || Npc_GetTrueGuild(hero) == GIL_KDW) { Trade_ChangeBuyMultiplier (1077936128); // 3.0 Trade_ChangeSellMultiplier (1041865113); // 0.15 } else { Trade_ChangeBuyMultiplier (1073741824); // 2.0 Trade_ChangeSellMultiplier (1045220556); // 0.2 }; };
Автор: George_M
09.08.2011
0 коммент.:
Отправить комментарий