-
Posts
548 -
Joined
-
Last visited
-
Days Won
6 -
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by Mind Rapist
-
-
-
4 hours ago, OtherChoice said:
Ok after testing the original bugfix you linked i found the problem, the m_akSimplePlayerInfo array is filled in a wrong way this is the solution:
In game/char.cpp at void CHARACTER::PointsPacket() change as following
void CHARACTER::PointsPacket() { if (!GetDesc()) return; TPacketGCPoints pack; pack.header = HEADER_GC_CHARACTER_POINTS; pack.points[POINT_LEVEL] = GetLevel(); pack.points[POINT_EXP] = GetExp(); pack.points[POINT_NEXT_EXP] = GetNextExp(); pack.points[POINT_HP] = GetHP(); pack.points[POINT_MAX_HP] = GetMaxHP(); pack.points[POINT_SP] = GetSP(); pack.points[POINT_MAX_SP] = GetMaxSP(); pack.points[POINT_GOLD] = GetGold(); pack.points[POINT_STAMINA] = GetStamina(); pack.points[POINT_MAX_STAMINA] = GetMaxStamina(); for (int i = POINT_ST; i < POINT_IQ + 1; ++i) pack.points[i] = GetRealPoint(i); for (int i = POINT_IQ + 1; i < POINT_MAX_NUM; ++i) pack.points[i] = GetPoint(i); GetDesc()->Packet(&pack, sizeof(TPacketGCPoints)); }
then at void CHARACTER::Disconnect add this line
if (GetDesc()) { /*add this*/ PointsPacket(); /* */ packet_point_change pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE; pack.dwVID = m_vid; pack.type = POINT_PLAYTIME; pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000; pack.amount = 0; GetDesc()->Packet(&pack, sizeof(struct packet_point_change)); GetDesc()->BindCharacter(NULL); // BindDesc(NULL); }
then in client source
PythonNetworkStreamPhaseGame.cpp -> bool CPythonNetworkStream::RecvPointChange() ------->Make these changes case POINT_PLAYTIME: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].dwPlayMinutes = PointChange.value; break; case POINT_LEVEL: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break; /*case POINT_ST: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break; case POINT_DX: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break; case POINT_HT: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break; case POINT_IQ: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break;*/ case POINT_ST: case POINT_DX: case POINT_HT: case POINT_IQ: __RefreshStatus(); __RefreshSkillWindow(); break;
Every other thing is like original thread
Tested and working.
I removed all the extra steps and left only what the post shows. Then I followed the steps above for char.cpp and PythonNetworkStreamPhaseGame.cpp. The problem is still here with a little difference... Now the horse stats are displayed only when during the logout, character rides a horse. I just don't get it we tried everything.
EDIT: Ok that was my bad actually. The problem is fixed!!!
I forgot to change
for (int i = POINT_ST; i < POINT_IQ + 1; ++i) pack.points[i] = GetRealPoint(i);
in PointsPacket()
was:
for (int i = POINT_ST; i < POINT_MAX_NUM; ++i) pack.points[i] = GetPoint(i);
but now I believe it's all right!
Thank you so much for your time. Lots of respect not just for helping me find a solution but also for not giving up on me. Cheers to you man
-
Try apply.AFFECT_STUN or apply.AFF_STUN
-
10 hours ago, OtherChoice said:
Oh ok i quite didn't get it, anyhow that's the solution you are looking for
This is you void CHARACTER::Disconnect(...) //ADD this PointChange(POINT_ST, 0); PointChange(POINT_DX, 0); PointChange(POINT_IQ, 0); PointChange(POINT_HT, 0); //end packet_point_change pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE; pack.dwVID = m_vid; pack.type = POINT_PLAYTIME; pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000; pack.amount = 0; pack.point_ST = GetPoint(POINT_ST); pack.point_DX = GetPoint(POINT_DX); pack.point_HT = GetPoint(POINT_HT); pack.point_IQ = GetPoint(POINT_IQ); GetDesc()->Packet(&pack, sizeof(struct packet_point_change)); /*if (GetHorseST() > GetPoint(POINT_ST)) PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST)); if (GetHorseDX() > GetPoint(POINT_DX)) PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX)); REMOVE ALL THIS if (GetHorseHT() > GetPoint(POINT_HT)) PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT)); if (GetHorseIQ() > GetPoint(POINT_IQ)) PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));*/
Thanks. I tried it but it didn't work.
I tried adding the PointChange(POINT_X, 0) at the top of the function and then I tried it right above the packet initialization, none worked. I also tried the PointsPacket.points in PythonNetworkStreamPhaseLoading.cpp and then I tried again with PointsChange.point_XX from the new packet you showed me, where PointsChange = TPacketGCPointChange PointsChange. None of these worked.
-
Have a look at questlua_affect.cpp->int aff_affect(lua_state * L)
int affect_add(lua_State * L) { if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2) || !lua_isnumber(L, 3)) { sys_err("invalid argument"); return 0; } CQuestManager & q = CQuestManager::instance(); BYTE applyOn = (BYTE) lua_tonumber(L, 1); LPCHARACTER ch = q.GetCurrentCharacterPtr(); if (applyOn >= MAX_APPLY_NUM || applyOn < 1) { sys_err("apply is out of range : %d", applyOn); return 0; } if (ch->FindAffect(AFFECT_QUEST_START_IDX, applyOn)) // 퀘스트로 인해 같은 곳에 효과가 걸려있으면 스킵 return 0; long value = (long) lua_tonumber(L, 2); long duration = (long) lua_tonumber(L, 3); ch->AddAffect(AFFECT_QUEST_START_IDX, aApplyInfo[applyOn].bPointType, value, 0, duration, 0, false); return 0; }
where L1 = affect ID, L2 = affect value, L3 = duration.If you use /stun MyChar as a GM and you refresh player.affect in the database you will see a new affect under the dwPID of the character stunned. The bApplyOn value is the id of the affect in the system (our case 210). If you want to check your affect ids, open the file affect.h in game/src and search for the following:
enum EAffectTypes { AFFECT_NONE, AFFECT_MOV_SPEED = 200, AFFECT_ATT_SPEED, AFFECT_ATT_GRADE, AFFECT_INVISIBILITY, AFFECT_STR, AFFECT_DEX, // 205 AFFECT_CON, AFFECT_INT, AFFECT_FISH_MIND_PILL, AFFECT_POISON, AFFECT_STUN, // 210 AFFECT_SLOW, AFFECT_DUNGEON_READY, AFFECT_DUNGEON_UNIQUE, ...
As you can see, the ids start from 200 and go on. The AFFECT_STUN is the 10th in the row, which gives it the ID of 210. To be sure, open your affect.h and see your ID of AFFECT_STUN.
I also saw that you changed the value (0->1). The value on this affect is not important as it can only be a true (exists on the database table) or false (not found in the database table)
I hope this helps
-
I'm gonna make this as simple as it gets.
Run the following commands as root:
#service mysql-server stop #cd /var/db #tar -zcvf mysql.tar.gz ./mysql #rm -rf ./mysql
Reboot your machine. Once mysql-server service runs without a /var/db/mysql folder, it automatically creates it's own.
Run these now:
#service mysql-server stop #/usr/local/bin/mysqld_safe --skip-grant-tables & #mysql -u root mysql > INSERT INTO mysql.user (host, user, password, select_priv, insert_priv, update_priv, delete_priv, create_priv, drop_priv, reload_priv, shutdown_priv, process_priv, file_priv, grant_priv, references_priv, index_priv, alter_priv, show_db_priv, super_priv, create_tmp_table_priv, lock_tables_priv, execute_priv, repl_slave_priv, repl_client_priv, create_view_priv, show_view_priv, create_routine_priv, alter_routine_priv, create_user_priv, event_priv, trigger_priv, create_tablespace_priv) VALUES ('%', 'root', PASSWORD('your-remote-root-password'), 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y',); > flush privileges; > exit; #killall mysqld #service mysql-server start
WARNING: I'm using Maria-DB, not MySQL, which I'm strongly suggesting to do as well. If not, your system may defer from mine. There for you should check the INSERT command and modify it according to your fields. To see your fields type the command below right before INSERT INTO
SELECT * FROM mysql.user;
If you run this and see that a root user with % host is already there, INSERT won't work. Instead, change the password like this:
> UPDATE mysql.user SET password=PASSWORD('your-specified-password') WHERE user='root';
and after that continue as displayed above.
When this is done and you check that you can log in MySQL from Navicat (or your software) copy the tar file in /var/db into your local drive and open it. In your FTP software, go in the folder /var/db/mysql and drag & drop everything from your tar file EXCEPT mysql folder!!!
All this until now will definately solve your mysql database problem. For the other databases, download other Serverfiles and replace the tables that cannot be fixed. But again, DO NOT TOUCH mysql FOLDER! You can download any SF you want (Fliege, Maxmi, Invoice), the databases should be the same.
I hope this was helpful.
Best regards
-
There are 2 ways to do this.
1) Direct quest edit
PROS:
- Quick, simple fix, anyone can do it
- Bypasses immunity
CONS:
- Not as stable as 2nd way
2) Source edit
PROS:
- Stable solution
- Your very own lua function on stunning people
CONS:
- Does NOT bypass immunity (people with immunity attribute on their shield won't be affected by this)
- More advanced implementation (recommended to back-up files, more advanced knowledge needed to edit according to your specifications)
- Not tested (by me)
This method will require you to compile a new QC file (add the new command in game/src/quest/quest_functions and then gmake -j20 in that directory)
Direct quest edit solution
In this example I will be using the item by vnum 31001
stun_quest.lua:
Spoilerquest stun_quest begin state start begin when 31001.use begin affect.add(210, 0, 2) -- Replace 2 with the duration of the affect you want to set (in seconds). end end end
Source edit solution
Go to game/src and edit the following in questlua_affect.cpp:
SpoilerAdd this to the inclludes:
#include battle.h
Find this function:
int affect_remove_all_collect( lua_State* L ) { ... }
Add below the closing curly brace:
int affect_stun() { CQuestManager & q = CQuestManager::instance(); LPCHARACTER ch = q.GetCurrentCharacterPtr(); ch->AddAffect(AFFECT_QUEST_START_IDX, AFFECT_STUN, 0, 0, 2, 0, false); // Edit 2 by your stun duration specification (in seconds) return 0; }
And of course find:
{ "get_apply_on", affect_get_apply_on },
and add this below:
{ "stun", affect_stun },
After that, you can use this in a quest like this:
stun_quest.lua
quest stun_quest begin state start begin when 31001.use begin affect.stun() end end end
REMEMBER: If you use the second way, you need to add affect.stun in quest_functions, both in SF/locale/country/quest and game/src/quest and recompile the QC in game/src/quest
I hope you found this helpful. Again, the second way is not tested and could be bugged (but I don't think so)
Best regards
- 1
-
10 hours ago, OtherChoice said:
The way you are trying to work with won't go anywhere, first, the point you are packing are in a wrong place, since the first time ComputePoints() is exectuted it will check whether your horse has higher stats than yours and then replace them if so and will however pack and send them to client. If you want to make sure you have your real stat points you need to create the packet inside CHARACTER::ComputePoints() function not in void CHARACTER::Disconnect. Next point is the packet you are using: since packet_point_change (HEADER_GC_CHARACTER_POINT_CHANGE) has already a defined behavior (it has 3 different behavior actually, in PhaseGame, PhaseSelect and PhaseLoading) i suggest you to avoid using it.
Moreover if your goal is to always show base stats and hide horse bonuses, you can skip the whole client part and do in a simpler way.
I will first explain how to get both base Stats and horse Stats.I just tried the code i wrote and everything works fine. There's just a couple of thing i missed when answering
Before TPacketGCBaseStats pack add this:
...
PointChange(POINT_ST, 0);
PointChange(POINT_DX, 0);
PointChange(POINT_IQ, 0);
PointChange(POINT_HT, 0);
TPacketGCBaseStats pack;
pack.header = HEADER_GC_BASE_STATS;
...then in PythonNetworkStreamPhaseGame.cpp:
void CPythonNetworkStream::GamePhase() { ... switch (header) { case HEADER_GC_OBSERVER_ADD: ret = RecvObserverAddPacket(); break; .... case HEADER_GC_BASE_STATS: ret = RecvBaseStatsPacket(); break; } } then after bool CPythonNetworkStream::RecvPointChange() { ... } add bool CPythonNetworkStream::RecvBaseStatsPacket() { TPacketGCBaseStats pack; if (!Recv(sizeof(TPacketGCBaseStats), &pack)) { Tracen("Recv Base Stats Packet Error"); return false; } //here you can do whatever you like with those number, to make sure you everything runs smoothly you can try this TraceError("Point_ST = %d, Point_DX = %d, Point_HT = %d, Point_IQ = %d \n", pack.point_ST, pack.point_DX, pack.POINT_HT, pack.point_IQ); // so you can run your client then check syserr.txt and look at the output } and in PythonNetworkStream.h after bool RecvPointChange(); add bool RecvBaseStatsPacket();
____________________________________________________________________________________________________
If you want to totally hide horse stats you can do something like this:
in char.cpp change void CHARACTER::PointChange(BYTE type, int amount, bool bAmount, bool bBroadcast) to
void CHARACTER::PointChange(BYTE type, int amount, int baseAmount=0, bool bAmount, bool bBroadcast) and change the definition in char.h as well (without =0 in the header file)
then at the end of the function you will find
if (GetDesc()) { struct packet_point_change pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE; pack.dwVID = m_vid; pack.type = type; pack.value = val; if (bAmount) pack.amount = amount; else pack.amount = 0; if (!bBroadcast) GetDesc()->Packet(&pack, sizeof(struct packet_point_change)); else PacketAround(&pack, sizeof(pack)); } } and change it like this if (GetDesc()) { struct packet_point_change pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE; pack.dwVID = m_vid; pack.type = type; pack.value = baseAmount ? baseAmount : val; if (bAmount) pack.amount = amount; else pack.amount = 0; if (!bBroadcast) GetDesc()->Packet(&pack, sizeof(struct packet_point_change)); else PacketAround(&pack, sizeof(pack)); } }
Lastly you need to edit char.cpp void CHARACTER::ComputePoints() find if (GetMountVnum()) { if (GetHorseST() > GetPoint(POINT_ST)) PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST)); if (GetHorseDX() > GetPoint(POINT_DX)) PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX)); if (GetHorseHT() > GetPoint(POINT_HT)) PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT)); if (GetHorseIQ() > GetPoint(POINT_IQ)) PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ)); } and change it like this if (GetMountVnum()) { if (GetHorseST() > GetPoint(POINT_ST)) PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST), GetPoint(POINT_ST)); if (GetHorseDX() > GetPoint(POINT_DX)) PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX), GetPoint(POINT_DX)); if (GetHorseHT() > GetPoint(POINT_HT)) PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT), GetPoint(POINT_HT)); if (GetHorseIQ() > GetPoint(POINT_IQ)) PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ), GetPoint(POINT_IQ)); }
Done.
Thank you so much for these information they were very helpful, but my goal is not to hide the horse stats in general, just in character select. I'm trying to hide them the same way item attributes are hidden: hidden in character select, showing everywhere else.
What I did with the client and the packet set in Disconnect() came from this post:
-
Thanks for the reply. I hate to ask but since I'm not too familliar with the whole system yet, can you give me an example please?
-
2 hours ago, OtherChoice said:
In Server source game/char.cpp in ComputePoints()
if (IsPC()) { if (GetMountVnum()) { if (GetHorseST() > GetPoint(POINT_ST)) PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST)); if (GetHorseDX() > GetPoint(POINT_DX)) PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX)); if (GetHorseHT() > GetPoint(POINT_HT)) PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT)); if (GetHorseIQ() > GetPoint(POINT_IQ)) PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ)); } }
This way horse stats will override lower stats. Those numbers are then packeted and sent to client. You could create a new packet sending base stats to client. To recive base stats from game use game/char.cpp int CHARACTER::GetPoint(type) where type is POINT_ST, POINT_DX, POINT_HT, POINT_IQ example:
game/packet.h && UserInterface/packet.h enum { HEADER_CG_HANDSHAKE = 0xdc, .... HEADER_GC_BASE_STATS = (your_value), typedef struct base_stats { BYTE header; DWORD point_ST; DWORD point_DX; DWORD point_HT; DWORD point_IQ; } TPacketGCBaseStats;
then send this packet from somewhere:
if (IsPC()) { if (GetMountVnum()) { TPacketGCBaseStats pack; pack.header = HEADER_GC_BASE_STATS; pack.point_ST = GetPoint(POINT_ST); pack.point_DX = GetPoint(POINT_DX); pack.point_HT = GetPoint(POINT_HT); pack.point_IQ = GetPoint(POINT_IQ); ch->GetDesc()->Packet(&pack, sizeof(pack)); if (GetHorseST() > GetPoint(POINT_ST)) PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST)); if (GetHorseDX() > GetPoint(POINT_DX)) PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX)); if (GetHorseHT() > GetPoint(POINT_HT)) PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT)); if (GetHorseIQ() > GetPoint(POINT_IQ)) PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ)); }
And then recive it from client and do whatever you like with those.
REMEMBER to declare both the packet header and the typedef struct inside packet.h of client binary as well.
I tested it and it didn't quite work. So I already had a packet in char.cpp->void CHARACTER:: Disconnect(const char * c_pszReason) and I changed it like this:
packet_point_change pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE; pack.dwVID = m_vid; pack.type = POINT_PLAYTIME; pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000; pack.amount = 0; pack.point_ST = GetPoint(POINT_ST); pack.point_DX = GetPoint(POINT_DX); pack.point_HT = GetPoint(POINT_HT); pack.point_IQ = GetPoint(POINT_IQ); GetDesc()->Packet(&pack, sizeof(struct packet_point_change)); if (GetHorseST() > GetPoint(POINT_ST)) PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST)); if (GetHorseDX() > GetPoint(POINT_DX)) PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX)); if (GetHorseHT() > GetPoint(POINT_HT)) PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT)); if (GetHorseIQ() > GetPoint(POINT_IQ)) PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
and then I changed this in UserInterface/PythonNetworkStreamPhaseLogin.cpp:
for (DWORD i = 0; i < POINT_MAX_NUM; ++i) { CPythonPlayer::Instance().SetStatus(i, PointsPacket.points[i]); TPacketGCPointChange PointsPacketChange; if (i == POINT_LEVEL) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointsPacket.points[i]; else if (i == POINT_ST) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointsPacketChange.point_ST; else if (i == POINT_HT) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointsPacketChange.point_HT; else if (i == POINT_DX) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointsPacketChange.point_DX; else if (i == POINT_IQ) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointsPacketChange.point_IQ; }
and I edited the packet.h files of course.
The result was that not only the problem continued to exist, but once the client starts, if the character logs out once with horse stats they are displayed each time they do, even if they don't ride a horse the next time! And not only that, when the character rides a horse in game, the HT, IQ, ST and DEX get updated but HP and SP are not updated!
-
So if I did something like this in questlua_pc.cpp->int pc_give_or_drop_item(lua_State* L)
LogManager::instance().QuestRewardLog(pPC->GetCurrentQuestName().c_str(), ch->GetPlayerID(), ch->GetLevel(), dwVnum, icount); if (dwVnum->IsStackable() && !IS_SET(dwVnum->GetAntiFlag(), ITEM_ANTIFLAG_STACK)) { BYTE bCount = dwVnum->GetCount(); for (int i = 0; i < INVENTORY_MAX_NUM; ++i) { LPITEM item2 = ch->GetInventoryItem(i); if (!item2) continue; if (item2->GetVnum() == item->GetVnum()) { int j; for (j = 0; j < ITEM_SOCKET_MAX_NUM; ++j) if (item2->GetSocket(j) != dwVnum->GetSocket(j)) break; if (j != ITEM_SOCKET_MAX_NUM) continue; BYTE bCount2 = std::min(200 - item2->GetCount(), bCount); bCount -= bCount2; item2->SetCount(item2->GetCount() + bCount2); if (bCount == 0) { LPITEM item = ch->AutoGiveItem(dwVnum, icount); } } }
would that work or I'm missing something?
- 1
-
-
1 hour ago, Krusty said:
Fixxed already. It was a big inside the source but thanks anyway
Would you mind showing us how can we fix this too?
-
-
-
On 12/6/2015 at 1:22 PM, Ken said:
At first, LoadMonsterAreInfo's first error is coming from regen.txt. If you don't have this file in your pack. System will give this error. As galet said, you're just hidding that.
char c_szFileName[256]; sprintf(c_szFileName, "%s\\regen.txt", GetMapDataDirectory().c_str()); LPCVOID pModelData; CMappedFile File; if (!CEterPackManager::Instance().Get(File, c_szFileName, &pModelData)) { //TraceError(" CMapOutdoorAccessor::LoadMonsterAreaInfo Load File %s ERROR", c_szFileName); return false; }
The code is already explain itself.
If you want to fix it, here is a fix for you.
bool CMapOutdoor::LoadMonsterAreaInfo() { RemoveAllMonsterInfo(); // Remove All Monster Info char szFileName[256]; _snprintf(szFileName, sizeof(szFileName), "%s\\monsterareainfo.txt", GetMapDataDirectory().c_str()); LPCVOID pModelData; CMappedFile File; if (!CEterPackManager::Instance().Get(File, szFileName, &pModelData)) return false; CMemoryTextFileLoader textFileLoader; CTokenVector stTokenVector; textFileLoader.Bind(File.size(), pModelData); for (DWORD i = 0; i < textFileLoader.GetLineCount(); ++i) { if (!textFileLoader.SplitLine(i, &stTokenVector)) continue; stl_lowers(stTokenVector[0]); // Start to read MonsterAreaInfo.txt if (0 == stTokenVector[0].compare("m") || 0 == stTokenVector[0].compare("g")) { if (stTokenVector.size() < 11) { TraceError("CMapOutdoorAccessor::LoadMonsterAreaInfo Get MonsterInfo File Format ERROR! continue...."); continue; } CMonsterAreaInfo::EMonsterAreaInfoType eMonsterAreaInfoType; if (0 == stTokenVector[0].compare("m")) { eMonsterAreaInfoType = CMonsterAreaInfo::MONSTERAREAINFOTYPE_MONSTER; } else if (0 == stTokenVector[0].compare("g")) { eMonsterAreaInfoType = CMonsterAreaInfo::MONSTERAREAINFOTYPE_GROUP; } else { TraceError("CMapOutdoorAccessor::LoadMonsterAreaInfo Get MonsterInfo Data ERROR! continue...."); continue; } const std::string & c_rstrOriginX = stTokenVector[1].c_str(); const std::string & c_rstrOriginY = stTokenVector[2].c_str(); const std::string & c_rstrSizeX = stTokenVector[3].c_str(); const std::string & c_rstrSizeY = stTokenVector[4].c_str(); const std::string & c_rstrZ = stTokenVector[5].c_str(); const std::string & c_rstrDir = stTokenVector[6].c_str(); const std::string & c_rstrTime = stTokenVector[7].c_str(); const std::string & c_rstrPercent = stTokenVector[8].c_str(); const std::string & c_rstrCount = stTokenVector[9].c_str(); const std::string & c_rstrVID = stTokenVector[10].c_str(); long lOriginX, lOriginY, lSizeX, lSizeY, lZ, lTime, lPercent; CMonsterAreaInfo::EMonsterDir eMonsterDir; DWORD dwMonsterCount; DWORD dwMonsterVID; lOriginX = atol(c_rstrOriginX.c_str()); lOriginY = atol(c_rstrOriginY.c_str()); lSizeX = atol(c_rstrSizeX.c_str()); lSizeY = atol(c_rstrSizeY.c_str()); lZ = atol(c_rstrZ.c_str()); eMonsterDir = (CMonsterAreaInfo::EMonsterDir) atoi(c_rstrDir.c_str()); lTime = atol(c_rstrTime.c_str()); lPercent = atol(c_rstrPercent.c_str()); dwMonsterCount = (DWORD) atoi(c_rstrCount.c_str()); dwMonsterVID = (DWORD) atoi(c_rstrVID.c_str()); CMonsterAreaInfo * pMonsterAreaInfo = AddMonsterAreaInfo(lOriginX, lOriginY, lSizeX, lSizeY); pMonsterAreaInfo->SetMonsterAreaInfoType(eMonsterAreaInfoType); if (CMonsterAreaInfo::MONSTERAREAINFOTYPE_MONSTER == eMonsterAreaInfoType) pMonsterAreaInfo->SetMonsterVID(dwMonsterVID); else if (CMonsterAreaInfo::MONSTERAREAINFOTYPE_GROUP == eMonsterAreaInfoType) pMonsterAreaInfo->SetMonsterGroupID(dwMonsterVID); pMonsterAreaInfo->SetMonsterCount(dwMonsterCount); pMonsterAreaInfo->SetMonsterDirection(eMonsterDir); } } return true; }
The system cannot read the actual file. File name is MonsterAreaInfo.txt but system is trying to read regen.txt.
If you want, you can change monsterareainfo.txt with regen.txt - result will be same.
Kind Regards ~ Ken
Epic save! Thanks!
- 1
-
17 minutes ago, PACI said:
Probably the client sniffing around. That exact character (along with brackets and vertical bar) is used for parsing quests' strings sent by the server. At this point, you may have noticed that the client doesn't only receives whatever text a quest window has, but also an event type bound to that said text, being it formatting, window resizing, item previews and whatnot.
Those actions are read this way.
This is what the server will send to the client, using the example you provided above:[QUESTION resume;0|1;Hi, how are you today;|2;Close]
resume stands for, eh.. a suspended state, can be said I guess. Meaning that it requires the player to answer. Everything else are necessary data the binary will send to the python-side of your client in order to create the so well known: chat-event. In order words, the buttons.
My suggestion is to jump into your PythonEventManager class for further info. The parser is in EterLib/parser.*
Thank you so much for your reply. I searched in the files you mentioned and I found the check that handles this character in parser.cpp
else if (c == ';') { isValue = true; }
I tried changing this to false but the result was not what I expected... I do not understand the most out of the code yet so I have to ask for a simple example. I thought maybe sending signal-character will do the trick. For example, I send ^ and write another check in this function that replaces
^[SPACE][END-OF-LINE]
with the character. The only problem is that I don't know how to edit the string's characters so I'm gonna have to request an example.
Again, thank you so much for the reply, it really helped a lot.
-
I've noticed this one since the beginning but for some reason I've been waiting until now to ask.
Let's say I'm writing a dialog with NPC X and when I click on it I want it to say:
Hi, how are you today;
So I'm writing the classic when XXXXXX.chat."Hi, how are you today;" and I'm compiling but when I click in the game the ; is missing! So it just says:
Hi, how are you today
I haven't yet find what filters the character so I'm asking you. I've looked in questlua.cpp and questlua_global.cpp but didn't find anything.
If anyone knows I'm also trying to find a way to increase the dialog width (after a line ends, there is just soooo much right padding!)
-
I have those lines in my Client source
PythonNetworkStreamPhaseLoading.cpp -> bool CPythonNetworkStream::__RecvPlayerPoints()
for (DWORD i = 0; i < POINT_MAX_NUM; ++i) { CPythonPlayer::Instance().SetStatus(i, PointsPacket.points[i]); if (i == POINT_LEVEL) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointsPacket.points[i]; else if (i == POINT_ST) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointsPacket.points[i]; else if (i == POINT_HT) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointsPacket.points[i]; else if (i == POINT_DX) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointsPacket.points[i]; else if (i == POINT_IQ) m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointsPacket.points[i]; }
PythonNetworkStreamPhaseGame.cpp -> bool CPythonNetworkStream::RecvPointChange()
case POINT_PLAYTIME: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].dwPlayMinutes = PointChange.value; break; case POINT_LEVEL: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break; case POINT_ST: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break; case POINT_DX: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break; case POINT_HT: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break; case POINT_IQ: m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointChange.value; __RefreshStatus(); __RefreshSkillWindow(); break;
But there is a problem with this code. If I'm riding my horse, it returns the stats the character has while riding.
For example if a character has INT: 6 and starts riding, the 6 will become 38.
If this code executes while the character is riding the horse, POINT_IQ will return 38 instead of the real INT (6).
Is there any way to get the real values?
-
-
-
I'm having the bug showing on the video (watch left window). The shaman targets an NPC, therefore, if she performs a buff skill, she will get the buff. But only her client will see the skill's effect on her body, everybody else will see the effect on the NPC's body. Can someone post or link a fix please?
- 1
-
I need all these as well... It's a whole new re-construction of the skills! Also, Lasting fire has a new, more realistic effect on character body.
- 1
-
dragging items trade [Problem]
in Community Support - Questions & Answers
Posted
Most probably a Python problem, unless it appeared once you compiled something. What does your syserr say?