Думаю, нет надобности объяснять актуальность данной проблемы. В теме по скриптингу уже обсуждалось возможность динамического управления соотношением цен с помощью пакета 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 коммент.:
Отправить комментарий