Jump to content

OtherChoice

Inactive Member
  • Posts

    91
  • Joined

  • Last visited

  • Days Won

    3
  • Feedback

    0%

Everything posted by OtherChoice

  1. Is It possible to use a weakref to self not to unroll lambda expressions? for example like this from _weakref import ref for materialRow in self.materialSlots: j = 0 for material in materialRow: material.SetOverInItemEvent(lambda i= ref(self), trash = 0, rowIndex = row, col = j: i.__OverInMaterialSlot(trash, rowIndex, col)) Or would the garbage collector still find +1 references?
  2. @enisina Maybe I didn't explain my thoughts correctly, sorry. What I meant is to add delete pkGrid; to the already existing method override . No excess code, it is already in your source.
  3. Nice shot. For better code management and reusability you could remove the delete from the if (pkOldGrid) check and put it into the override method CGrid::CGrid(CGrid * pkGrid, int w, int h) : m_iWidth(w), m_iHeight(h) like this: CGrid::CGrid(int w, int h) : m_iWidth(w), m_iHeight(h) { m_pGrid = new char[m_iWidth * m_iHeight]; memset(m_pGrid, 0, sizeof(char) * m_iWidth * m_iHeight); } CGrid::CGrid(CGrid * pkGrid, int w, int h) : m_iWidth(w), m_iHeight(h) //<- if you add delete pkGrid here you can call M2_NEW CGrid(CGrid*, width, height) and it will delete the old pointer of safebox function at the end of this method { m_pGrid = new char[m_iWidth * m_iHeight]; int iSize = std::MIN(w * h, pkGrid->m_iWidth * pkGrid->m_iHeight); thecore_memcpy(m_pGrid, pkGrid->m_pGrid, sizeof(char) * iSize); //here delete pkGrid; }
  4. @Gurgarath Hello, I'm trying to reproduce the bug but I'm working on a "worked-around" source, do you know how this work around was made? EDIT: After a bit of testing, as i was expecting is a client fix made on skilltable.txt. Your solution is also not a real fix, this skill as the majority of them checks on client side for hit collision. So the real problem is in client data inconsistencies in skill range set in skilltable.txt and hit data from skill yongpa(_2,_3,_4).msa. The following are the "actual hitting" ranges, while range in skilltable.txt is the range your character walks up to before casting the skill, so basically those two values have to match. Group Event03 { MotionEventType 4 StartingTime 1.193431 DuringTime 0.200000 EnableHitProcess 1 AttackType 0 HittingType 1 StiffenTime 0.000000 InvisibleTime 0.500000 ExternalForce 0.000000 HitLimitCount 5 CollisionType 4 SphereDataCount 1 Group SphereData00 { Radius 200.000000 Position 0.000000 -200.000000 150.000000 } } Group Event04 { MotionEventType 4 StartingTime 1.445256 DuringTime 0.200000 EnableHitProcess 1 AttackType 0 HittingType 1 StiffenTime 0.000000 InvisibleTime 0.500000 ExternalForce 0.000000 HitLimitCount 5 CollisionType 4 SphereDataCount 1 Group SphereData00 { Radius 200.000000 Position 0.000000 -600.000000 150.000000 } } those hitting spheres are positioned in front of the character at radius distance from you and from the first sphere covering a total distance of 4*radius so 800, I suggest to use this value lowered by a 50 for latency and moving victims, you can fiddle with this value and get the desired result, for skilltable.txt (and skill_proto as well, DB is not used but if you want to add a check serverside for skillrange hacks and such you'd better have consistent data). So with current .msa file settings the correct value for skilltable.txt is 750; hitsphere, however, is noticeably smaller than the dragon head range. Another good solution would be to increase sphere radius to 250 (for each of the 4 msa) and skilltable.txt value to 950. This solution has been tested and works with no double damage computation( @Heathcliff™) and with the default m_me->OnMove(true) function (no need to change source). If you want any further explaination about OnMove usage here do not esitate to ask.
  5. Might be also a good idea to change data size for communicating structures like header of packets and sequence magic table (of course also change the table itself) currently unisgned char, more bits == more work for attacker. Those things will make packet forging attempts much harder. There are also packs which can be loaded, if client code gets rewrote wiser, after client-server first communication (majority of them, the ones you want to protect actually). Just combine those two factors (don't want to get too deep into it not to exploit it) and you will have a decent looking server packet decryption key system.
  6. Lol, best asnwer is in this small line.
  7. I'm not 100% sure but probably its managed on client source level with matrices of texture, depth stencyl, and such by Direct3d8
  8. Hello everyone, today i'm on my second day trying to expand dynamic shadows view range, i found many limiters here and there for example SHADOW_APPLY_MAX_DISTANCE, bShadow_cutoff but none of those seem to be really affecting shadow range, Dynamic Shadows are rendered inside a square (not a circle so radius like constants mentioned above or distance between mainInstance and targetInstance are not involved) around the current playing character. Do you guys know if there's a cube or a square for dynamic shadows to be rendered on, and if so where is it defined? Hope you can help me I can't really figure it out. SOLVED: matLightProj was set to 2400.0f x 2400.0f x 1 x 15000.0f, changing the height and width of projection matrix will project more shadows UPDATE: larger projection will upscale shadow texture so it results in a shadow quality reduction, it can be partially bypassed by increasing m_wShadowMapSize but only up to a limit of 8192 set by Direct3d8.
  9. @HITRONIf you use two screen setup you can use, move, click, watch Netflx on the other screen still playing at fullscreen on the first one (if you played either guild wars2 or blackdesert online you should have seen those settings, and I'm sure there are lot more games using this) [Hidden Content]
  10. The only variable in the formula is "k" which is the skillpower vaiable and ranges from 0.05 at level 1 to 1.25 at P. You have to ways of accomplish what you want, edit the formula to reach the cap you want at the current rate of change which implies intermediate values will follow the function. For example: or you can totaly remove the formula and manually enter the values from level 0 to 40 in a declared array accessible by the function short m_PartyAttackBonus[41] = { 1,2,3,4,5,/*YOUR 41 values here*/... }; and then change int Bonus = m_PartyAttackBous[ch->GetParty()->GetLeader()->GetSkillLevel(YOUR_LEADERSHIP_SKILL_VALUE)] it would be better if you add a check if the party leader exists( if (ch->GetParty()->GetLeader()) ), maybe it is not needed but you would want to test it before (having two chars in group with the leader logging off while the party member is attaccking monsters so he is constantly checking for those values)
  11. You can also use windef macros and use way less CWindows and workarounds, I made my client borderless (full screen over the taskbar but not locked as top window like actual fullscreen) with this exact method. Those macros, in the right execution order are: SetWindowLongPtr, SetRect, AdjustWindowRectEx, MoveWindow, SetWindowPos. You can have a look at how they are used in PythonApplication.cpp bool CPythonApplication::Create(PyObject * poSelf, const char * c_szName, int width, int height, int Windowed) for game window, but they can be applied to any window handler.
  12. run this query in player db and report the results: SELECT * FROM player.item WHERE id = 10019575; according to bt thats the ID of the item that crashes core when you try to remove it.
  13. I can't see anything wrong neither in this function, so probably you should check your db item_proto entries as suggested (you can also have a sys_err("deleting %d", item->GetVnum()) at the beginning of your DestroyItem() function, after /ip or /ipurge command load your character, with your latest item_proto entries (most likely there's nothing wrong with vanilla items) and then disconnect, if you get a core again you can check which item caused it in your sys_err since it will be last line before crash).
  14. The crash occured after a disconnect as you can see in the bt, the Disconnect() method and the ~CHARACTER destructor are called, for what i can see there's no problem with ClearItems() and DestroyItem(), post your CHARACTER::Destroy() method maybe there are more clues on what happened. It might be a double deletion of something since you get undefined behaviour if you try to delete an object through a pointer more that once. But the pointers in func args seem ok they don't look like bogus pointers. Or maybe @WeedHex is right and you got db incosistencies.
  15. float CalcAttackRating(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnoreTargetRating) This function calculates Attack rating, which is a hidden factor in damage calculation, calculated with two value(attackerAR-victimER) which range from 0.7 to 1 for attacker and from 0 to 0.3 for victim based on dex and level of attacker and victim. Basically this is a multiplier which can range from 0.4 (minattackerAR = 0.7 - maxvictimER = 0.3) to 1 (maxattackerAR=1 - minvictimER = 0) and it is applied to every damage you compute. If you change those values every damage you will compute (with or without costume buff) will do more damage so changing that function won't works as you expect: Yes you will do more damage with costume buff but you will also do more damage without it, you are changing the way the game calculates this multiplier every time, not just the % bonus damage given from a said source.
  16. % damages are calculated based on your damage without that modifier, if you have 10% bonus on costume, you will deal 10% more damage. For example if my damage is 3000, 10% mob would give me around 300 more damage; if my damage is 8000 then that 10% would add 800 damage. You can't change how much 10% is without increasing the base number, you can't change how percentages work because your math will loose consistency and not a single compiler or machine can work with inconsistent information. What you can do is to edit the bonus percentage it gives: if your damage is around 3000 (since you have 300 bonus damage from 10%) you can increase %damage to something between 25-30% and you will have your 800-900 damages bonus from costume
  17. The problem is the m_Victim, each LPCHARACTERS stores the target and, even if ChangeVictimByAggro(args) won't be executed since type = DAMAGE_TYPE_POISON, the monster will keep the target pointer to their last victim, you need to also remove the resurrected LPCHARACTER as victim of nearby monsters. To do so you can use some simple structs, I already posted this solution for Invisibility skill. in char.cpp find void CHARACTER::ReviveInvisible(int iDur) and replace whole function struct RemoveInvisibleVictim { RemoveInvisibleVictim(LPCHARACTER pkOldVictim) { m_pkOldVictim = pkOldVictim; } void operator () (LPENTITY ent) { if (ent->IsType(ENTITY_CHARACTER)) { LPCHARACTER pkChr = (LPCHARACTER) ent; if (pkChr && pkChr->IsMonster()) { LPCHARACTER pkVictim = pkChr->GetVictim(); if (pkVictim && pkVictim == m_pkOldVictim) { LPCHARACTER new_victim = pkChr->GetNewNearestVictim(pkChr, m_pkOldVictim); pkChr->SetVictim(new_victim); } } } } LPCHARACTER m_pkOldVictim; }; void CHARACTER::ReviveInvisible(int iDur) { if (GetSectree()) { RemoveInvisibleVictim f(this); GetSectree()->ForEachAround(f); } AddAffect(AFFECT_REVIVE_INVISIBLE, POINT_NONE, 0, AFF_REVIVE_INVISIBLE, iDur, 0, true); } in char_battle.cpp add (and define it in char.h: LPCHARACTER GetNewNearestVictim(LPCHARACTER pkChr, LPCHARACTER pkVictimOld); ) LPCHARACTER CHARACTER::GetNewNearestVictim(LPCHARACTER pkChr, LPCHARACTER pkVictimOld) { if (NULL == pkChr) pkChr = this; float fMinDist = 99999.0f; LPCHARACTER pkVictim = NULL; TDamageMap::iterator it = m_map_kDamage.begin(); while (it != m_map_kDamage.end()) { const VID & c_VID = it->first; ++it; LPCHARACTER pAttacker = CHARACTER_MANAGER::instance().Find(c_VID); if (!pAttacker) continue; if (pAttacker->IsAffectFlag(AFF_EUNHYUNG) || pAttacker->IsAffectFlag(AFF_INVISIBILITY) || pAttacker->IsAffectFlag(AFF_REVIVE_INVISIBLE)) continue; float fDist = DISTANCE_APPROX(pAttacker->GetX() - pkChr->GetX(), pAttacker->GetY() - pkChr->GetY()); if (fDist < fMinDist && !pAttacker->IsDead() && pAttacker != pkVictimOld) { pkVictim = pAttacker; fMinDist = fDist; } } return pkVictim; } And then clean some miscoding: In char_affect.cpp at CHARACTER::AddAffect(args...) if bool bOverride (one of the function arguments) is true it will first reset a said flag calling if (pkAff && bOverride) { ComputeAffect(pkAff, false); // if (GetDesc()) SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn); } WE change it as follows if (pkAff && bOverride) { ComputeAffect(pkAff, false, true); // ComputeAffect(Affect, !bOvveride, bOverride); if (GetDesc()) SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn); } But we do not need to reset said flag early in the function if we are going to set it back few moments later so we can change CHARACTER::ComputeAffect(args..) as follows: find void CHARACTER::ComputeAffect(CAffect * pkAff, bool bAdd) if (bAdd && pkAff->dwType >= GUILD_SKILL_START && pkAff->dwType <= GUILD_SKILL_END) { if (!GetGuild()) return; if (!GetGuild()->UnderAnyWar()) return; } if (pkAff->dwFlag) { if (!bAdd) m_afAffectFlag.Reset(pkAff->dwFlag); else m_afAffectFlag.Set(pkAff->dwFlag); } replace with void CHARACTER::ComputeAffect(CAffect * pkAff, bool bAdd, bool bTemp) { if (bAdd && pkAff->dwType >= GUILD_SKILL_START && pkAff->dwType <= GUILD_SKILL_END) { if (!GetGuild()) return; if (!GetGuild()->UnderAnyWar()) return; } if (pkAff->dwFlag) { if (!bAdd && !bTemp) m_afAffectFlag.Reset(pkAff->dwFlag); else if (bAdd) m_afAffectFlag.Set(pkAff->dwFlag); } //HEADER char.h find void ComputeAffect(CAffect * pkAff, bool bAdd); replace with void ComputeAffect(CAffect * pkAff, bool bAdd, bool bTemp = false); tested and working.
  18. Client sources are files which compile into your ".exe" application, they manage physics, graphics, incoming and outgoing data transfers, and use the resources contained in your client's pack folder, such as textures, 3d models (.gr2), python files and plain text files. Server sources are files which compile into your "game" and "db" (no extension since they're elf32) files hosted on the remote server. They manage incoming and outgoing data transfers, and use the resources contained in your database to evaluate formulas for pretty much anything. The only way to actually "use" them is compiling into the respective files, but you can change how they work on datas, or datas they work with.
  19. Also remember to set i386 os when debugging with gdb set gnutarget i386-marcel-freebsd
  20. @HITRON After a brief test i noticed that the flag AFF_EUNHYUNG is set after skill computation, so it needs a fix, i will edit the first post as well. Full fix tested and working in char.h add friend struct RemoveInvisibleVictim; then in char_skill.cpp add this struct struct RemoveInvisibleVictim{ RemoveInvisibleVictim(LPCHARACTER pkOldVictim) { m_pkOldVictim = pkOldVictim; } void operator () (LPENTITY ent) { if (ent->IsType(ENTITY_CHARACTER)) { LPCHARACTER pkChr = (LPCHARACTER) ent; if (pkChr && pkChr->IsMonster()) { LPCHARACTER pkVictim = pkChr->GetVictim(); if (pkVictim && pkVictim == m_pkOldVictim) { LPCHARACTER new_victim = pkChr->GetNearestVictim(pkChr); // or optional GetHighestDpsVictim(pkChr) if (new_victim != m_pkOldVictim) //NEED TO ADD CHECK HERE AFF_EUNHYUNG WILL BE SET LATER pkChr->SetVictim(new_victim); else pkChr->SetVictim(NULL); } } } } LPCHARACTER m_pkOldVictim; }; then in function (char_skill.cpp) int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel) add if (dwVnum == SKILL_EUNHYUNG && GetSectree()) { RemoveInvisibleVictim f(this); GetSectree()->ForEachAround(f); } OPTIONAL: GetHighestDpsVictim in char_battle.cpp LPCHARACTER CHARACTER::GetHighestDpsVictim(LPCHARACTER pkChr) { if (NULL == pkChr) pkChr = this; float fMinDist = 99999.0f; float fMaxDamage = 0.0f; LPCHARACTER pkVictim = NULL; TDamageMap::iterator it = m_map_kDamage.begin(); // 일단 주위에 없는 사람을 걸러 낸다. while (it != m_map_kDamage.end()) { const VID & c_VID = it->first; float fDamage = it->second.iTotalDamage; ++it; LPCHARACTER pAttacker = CHARACTER_MANAGER::instance().Find(c_VID); if (!pAttacker) continue; if (pAttacker->IsAffectFlag(AFF_EUNHYUNG) || pAttacker->IsAffectFlag(AFF_INVISIBILITY) || pAttacker->IsAffectFlag(AFF_REVIVE_INVISIBLE)) continue; float fDist = DISTANCE_APPROX(pAttacker->GetX() - pkChr->GetX(), pAttacker->GetY() - pkChr->GetY()); if (fDist < fMinDist && !pAttacker->IsDead() && fDamage > fMaxDamage) { pkVictim = pAttacker; fMaxDamage = fDamage; } } return pkVictim; }
  21. I think I did not explained my ideas correctly or clearly, I apologize. This is NOT a struct to check if anybody else is invisible, as you said. This struct checks who's attacking a said target, and you call it when that target enters invisibility. So basically when someone uses stealth skill, the server checks if any monster is attacking him, IF so it tells them to find someone else to attack. The check is on the monster attacking a target who's getting invisible.
  22. The aggro taken is from a damage map iterator hence the only players found by the function are player attacking the monster, moreover you can just create a different method for selecting your next target just the way you select the nearest. The already existing functions checks for invisibility affect when selecting target and they have no knowledge about a potential change of the affect, that's why when you enter invisibility you need to check sectree to tell who and who's not attacking you and inform them about your new state. example code for GetHighestDpsVictim(LPCHARACTER pkChr) { if (NULL == pkChr) pkChr = this; float fMinDist = 99999.0f; float fMaxDamage = 0.0f; LPCHARACTER pkVictim = NULL; TDamageMap::iterator it = m_map_kDamage.begin(); // 일단 주위에 없는 사람을 걸러 낸다. while (it != m_map_kDamage.end()) { const VID & c_VID = it->first; float fDamage = it->second.iTotalDamage; ++it; LPCHARACTER pAttacker = CHARACTER_MANAGER::instance().Find(c_VID); if (!pAttacker) continue; if (pAttacker->IsAffectFlag(AFF_EUNHYUNG) || pAttacker->IsAffectFlag(AFF_INVISIBILITY) || pAttacker->IsAffectFlag(AFF_REVIVE_INVISIBLE)) continue; float fDist = DISTANCE_APPROX(pAttacker->GetX() - pkChr->GetX(), pAttacker->GetY() - pkChr->GetY()); if (fDist < fMinDist && !pAttacker->IsDead() && fDamage > fMaxDamage) { pkVictim = pAttacker; fMaxDamage = fDamage; } } return pkVictim; }
  23. Right now I'm not able to test it but I think this is what you were looking for: in char.h add friend struct RemoveInvisibleVictim; then in char_skill.cpp add this struct struct RemoveInvisibleVictim{ RemoveInvisibleVictim(LPCHARACTER pkOldVictim) { m_pkOldVictim = pkOldVictim; } void operator () (LPENTITY ent) { if (ent->IsType(ENTITY_CHARACTER)) { LPCHARACTER pkChr = (LPCHARACTER) ent; if (pkChr && pkChr->IsMonster()) { LPCHARACTER pkVictim = pkChr->GetVictim(); if (pkVictim && pkVictim == m_pkOldVictim) { LPCHARACTER new_victim = pkChr->GetNearestVictim(pkChr); if (new_victim != m_pkOldVictim) //NEED TO ADD CHECK HERE AFF_EUNHYUNG WILL BE SET LATER pkChr->SetVictim(new_victim); else pkChr->SetVictim(NULL); } } } } LPCHARACTER m_pkOldVictim; }; then in function (char_skill.cpp) int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel) add if (dwVnum == SKILL_EUNHYUNG && GetSectree()) { RemoveInvisibleVictim f(this); GetSectree()->ForEachAround(f); } For any problem please reply providing as much informations as possible.
  24. Check everything is correct in view frustrum and spherelib inside client binary.
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.