OtherChoice

Member
  • Content Count

    85
  • Joined

  • Last visited

  • Days Won

    3

OtherChoice last won the day on May 8 2019

OtherChoice had the most liked content!

Community Reputation

36 Good

About OtherChoice

  • Rank
    Friendly

Profile Information

  • Gender
    Not Telling

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. OtherChoice

    open

    I'm not 100% sure but probably its managed on client source level with matrices of texture, depth stencyl, and such by Direct3d8
  2. OtherChoice

    solved

    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.
  3. OtherChoice

    open

    Yeah it works smoothly
  4. OtherChoice

    open

    @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) https://gyazo.com/a90ce1c347aa7d27eb0a67f2ca7052f0
  5. OtherChoice

    open

    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)
  6. OtherChoice

    open

    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.
  7. OtherChoice

    open

    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.
  8. OtherChoice

    open

    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).
  9. OtherChoice

    open

    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.
  10. OtherChoice

    solved

    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.
  11. OtherChoice

    solved

    % 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
  12. 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.
  13. OtherChoice

    open

    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.
  14. OtherChoice

    open

    Also remember to set i386 os when debugging with gdb set gnutarget i386-marcel-freebsd
  15. OtherChoice

    @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; }