Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.6] ladder disappear #418

Closed
ronpetit opened this issue Dec 24, 2013 · 25 comments
Closed

[7.6] ladder disappear #418

ronpetit opened this issue Dec 24, 2013 · 25 comments

Comments

@ronpetit
Copy link
Contributor

i'm having the same trouble as the issue #410 but you ever help the guy to fix that, you said that is because the server is sending the wrong stackpos to create the splash effect, so how i can prevent that?, i'm using the lastest avesta maded by ferrus so come on, i'm not using a entire crap

The problem is that if i'm standing in a ladder and some monsters hit me two times the ladder disappear until i walk away a lost the ladder in the screen

@otclient
Copy link

No, i couldn't find working tibia.dat editor. I mean i found one but it couldn't load tibia.dat.

Ronpetit if you will find working one please share with me.

@ronpetit
Copy link
Contributor Author

I found one, use the gray dat editor from otland, it works really nice, but mate, the solution is not to put the ladder on top order 3, because that make the ladder to apper in from of your character and that look weird, it fix the problem because it not disappear but that kind of solution is not right, with the cipsoft client it works well for me, so im asking to someone if they have a better solution

@TheSumm
Copy link
Collaborator

TheSumm commented Dec 25, 2013

If @LordHepipud is correct this is not a OTClient issue, it is a server issue.

@ronpetit
Copy link
Contributor Author

Are you sure?, because in the official 7.6 client that never happen, i will check my server source to see if with that i can fix it

@TheSumm
Copy link
Collaborator

TheSumm commented Dec 25, 2013

It was coded to work with the normal client, that does not mean the server code is correct in all cases.

@otclient
Copy link

It's 100% client issue, something is wrong with splash or ladder and for sure there should be source fix for it.
I'm not otclient creator so i don't know.

@ronpetit
Copy link
Contributor Author

I'm not sure that is 100% client issue, i'm checking right now my sources, @LordHepipud said that the server is sending a wrong stackpos to create the splash effect, i'm checking that part right now everything look fine, when something is in race "blood" it creates the splash

the item::createitem function is this

Item* Item::CreateItem(PropStream& propStream)
{
uint16_t _id;
if(!propStream.GET_USHORT(_id)){
return NULL;
}

const ItemType& iType = Item::items[_id];
uint8_t _count = 0;

if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){
    if(!propStream.GET_UCHAR(_count)){
        return NULL;
    }
}

return Item::CreateItem(_id, _count);

}

i don't know much about C++, but what i understand is that everything is fine, but later i will compare with TFS 1.0, don't close the issue

@LordHepipud
Copy link
Contributor

This is NOT a client issue. Those 7.6 Servers are mostly handling stackpos wrong or by sending inussificent data to the client (you can check that: Step on a carpet and become hit -> carpet will become removed after blood is added -> correct?). The reason why CIP's client is not "having" the ladder bug is simply because the internal handling is different. The OTClient is doing the handling correct - receiving packets for a wrong stackpos and overwriting the content (like an update).

Actually the correct handling from the server would be:

Tile has splash -> get stackpos from old splash and overwrite it -> send Client info that "new" item is placed on the same stackpos
Tile has no splash -> Splash is added to the tile -> afterwards all data from the specific tile is collected and send correctly to the client

How can this be a Client issue? I'm using 7.72 Protocol (besides RSA and XTEA encryption nearly identical) and I'm not having the problem, because I changed most parts of the very crap code base of this handling.

Check your Game::addThing() function inside your server. There should be a handling for splashes inside. Make sure that if a new splash is added Player::onUpdateTile() is called while for overwriting existing splashes Game::sendUpdateThing() is called.

@ronpetit
Copy link
Contributor Author

Well, if you are 100% sure that's not the client so i will close the issue, but maybe you can help me to solve it?, i don't know much about C++ but i understand what is needed

@LordHepipud
Copy link
Contributor

Sure thing. Please write an e-mail to support@phiadariasoft.com

@TheSumm
Copy link
Collaborator

TheSumm commented Dec 25, 2013

I tested on Yurots 0.9.4f and it seems to be working fine. If there is a splash on the tile it gets replaced and updated and if there is no splash it gets added.

if(item && item->isSplash()){
    if(tile->splash){
        int oldstackpos = tile->getThingStackPos(tile->splash);
        Item *oldsplash = tile->splash;

        oldsplash->isRemoved = true;
        FreeThing(oldsplash);

        tile->splash = item;

        sendUpdateThing(NULL, pos, item, oldstackpos);
    }
    else{
        tile->splash = item;
        sendAddThing(NULL,pos,tile->splash);
    }
}

I will close it then.

@TheSumm TheSumm closed this as completed Dec 25, 2013
@otclient
Copy link

Here is fix for avesta:
ctrl+f in current project search for g_game.FreeThing(oldSplash); and under it add:
onUpdateTile();

@ronpetit
Copy link
Contributor Author

@otclient It only solve the graphical problem, now the ladder don't disappear, but if you get some hits you won't be able to go up through the ladder, so you have to go away until the ladder gets out of your screen and then it will work, so there is another thing that left to edit

@otclient
Copy link

Try change toporder to 0. Ctrl+f search for "Item* item = tile->getItemByTopOrder"
In my server it works however when under the ladder is creature i cannot go up.

@LordHepipud
Copy link
Contributor

You can modify this behaviour at \modules\game_interface\gameinterface.lua

There are the control settings which action the Client is handling first. Performing use actions or attacking creatures.

function processMouseAction

@otclient
Copy link

Lord Hepipud, it's true works. :)

For ronpetit, "onUpdateTile();" must be in function "void Tile::__updateThing" too. Because when splash transform to smaller spalsh ladder dissapear again.

@otclient
Copy link

Wondering how to get ladder id by attackedcreature position. It's possible?

@TheSumm
Copy link
Collaborator

TheSumm commented Dec 26, 2013

g_game.findItemOfType(tile, [itemId], false, -1);

Ladder only has itemid 1386 I think in 7.6

@ronpetit
Copy link
Contributor Author

@otclient I cannot change the toporder to 0, i didnt find that line in my sources, but i add the onUpdateTile() to the __updatething

also did you find something interesting on the game_interface.lua?

@LordHepipud
Copy link
Contributor

Why can't you change this behaviour? Revmoving the g_game.attack() wont fix it yes - because the order is still wrong.
In classic control, you will have to change it like this:

  if useThing:isContainer() then
    if useThing:getParentContainer() then
      g_game.open(useThing, useThing:getParentContainer())
      return true
    else
      g_game.open(useThing)
      return true
    end
  elseif useThing:isMultiUse() then
    startUseWith(useThing)
    return true
  elseif useThing then
    g_game.use(useThing)
  elseif creatureThing and creatureThing ~= player and creatureThing:getPosition().z == autoWalkPos.z then
    g_game.attack(creatureThing)
    return true

However - this one will now deny you from attacking creatures by using the right mouse button. So you will have to implement something like TheSumm said, checking before the first action for specific items.

So it might look like this:

if useThing and useThing:getId() == 1948 then --Use ladder before doing anything else
g_game.use(useThing)
return true
elseif creatureThing and creatureThing ~= player and creatureThing:getPosition().z == autoWalkPos.z then
g_game.attack(creatureThing)
return true
elseif useThing:isContainer() then
if useThing:getParentContainer() then
g_game.open(useThing, useThing:getParentContainer())
return true
else
g_game.open(useThing)
return true
end

@ronpetit
Copy link
Contributor Author

Well, i put it like this:

-- classic control
else
if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
local player = g_game.getLocalPlayer()
if useThing and useThing:getId() == 1386 then --Use ladder before doing anything else
g_game.use(useThing)
return true
elseif attackCreature and attackCreature ~= player then
g_game.attack(attackCreature)
return true
elseif creatureThing and creatureThing ~= player and creatureThing:getPosition().z == autoWalkPos.z then
g_game.attack(creatureThing)
return true
elseif useThing:isContainer() then
if useThing:getParentContainer() then
g_game.open(useThing, useThing:getParentContainer())
return true
else
g_game.open(useThing)
return true
end
elseif useThing:isMultiUse() then
startUseWith(useThing)
return true
else
g_game.use(useThing)
return true
end

and it doesnt works mate =(

@otclient
Copy link

That works: (If still doesn't work change that toporder to 0 as i said some posts above. Search for "//First check items" and under it is needed function in game.cpp-->Thing* Game::internalGetThing.

-- classic control
else
if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
local player = g_game.getLocalPlayer()
if useThing and useThing:getId() == 1386 then
g_game.use(useThing)
return true
elseif attackCreature and attackCreature ~= player then
g_game.attack(attackCreature)
return true
elseif creatureThing and creatureThing ~= player and creatureThing:getPosition().z == autoWalkPos.z then
g_game.attack(creatureThing)
return true
elseif useThing:isContainer() then
if useThing:getParentContainer() then
g_game.open(useThing, useThing:getParentContainer())
return true
else
g_game.open(useThing)
return true
end
elseif useThing:isMultiUse() then
startUseWith(useThing)
return true
else
g_game.use(useThing)
return true
end
return true
elseif lookThing and keyboardModifiers == KeyboardShiftModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
g_game.look(lookThing)
return true
elseif lookThing and ((g_mouse.isPressed(MouseLeftButton) and mouseButton == MouseRightButton) or (g_mouse.isPressed(MouseRightButton) and mouseButton == MouseLeftButton)) then
g_game.look(lookThing)
return true
elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
createThingMenu(menuPosition, lookThing, useThing, creatureThing)
return true
elseif attackCreature and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
g_game.attack(attackCreature)
return true
elseif creatureThing and creatureThing:getPosition().z == autoWalkPos.z and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
g_game.attack(creatureThing)
return true
end
end

local player = g_game.getLocalPlayer()
player:stopAutoWalk()

if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then
player:autoWalk(autoWalkPos)
return true
end

return false
end

@ronpetit
Copy link
Contributor Author

everybody knows about this except me xD, @otclient i can't find where to put the toporder, look my Thing* Game::getInternalThing

Thing* Game::internalGetThing(Player* player, const Position& pos, int32_t index, uint32_t spriteId /*= 0*/, stackPosType_t type /*= STACKPOS_NORMAL*/)
{
    if(pos.x != 0xFFFF)
    {
        Tile* tile = getTile(pos.x, pos.y, pos.z);
        if(tile)
        {
            /*look at*/
            if(type == STACKPOS_LOOK)
            {
                Creature* c;
                if(tile->getTopThing() && (c = tile->getTopThing()->getCreature()))
                {
                    if(c && c->isInGhostMode() && !player->canSeeGhost(c))
                    {
                        CreatureVector v;
                        CreatureVector::iterator it;

                        Creature* ghostCreature = NULL;
                        for(it = tile->creatures.begin(); it != tile->creatures.end(); ++it)
                        {
                            if(!(*it)->isInGhostMode() || player->canSeeGhost((*it)))
                            {
                                ghostCreature = (*it);
                                break;
                            }
                        }

                        if(ghostCreature)
                            return ghostCreature;

                        if(tile->getTopDownItem())
                            return tile->getTopDownItem();

                        if(tile->getTopTopItem())
                            return tile->getTopTopItem();

                        return tile->ground;
                    }
                    return c;
                }
                return tile->getTopThing();
            }

            Thing* thing = NULL;
            /*for move operations*/
            if(type == STACKPOS_MOVE)
            {
                Item* item = tile->getTopDownItem();
                if(item && !item->isNotMoveable())
                    thing = item;
                else
                    thing = tile->getTopCreature();
            }
            /*use item*/
            else if(type == STACKPOS_USE)
                thing = tile->getTopDownItem();
            else
                thing = tile->__getThing(index);

            if(player)
            {
                //do extra checks here if the thing is accessable
                if(thing && thing->getItem())
                {
                    if(tile->hasProperty(ISVERTICAL))
                    {
                        if(player->getPosition().x + 1 == tile->getPosition().x)
                            thing = NULL;
                    }
                    else if(tile->hasProperty(ISHORIZONTAL))
                    {
                        if(player->getPosition().y + 1 == tile->getPosition().y)
                            thing = NULL;
                    }
                }
            }
            return thing;
        }
    }
    else
    {
        //container
        if(pos.y & 0x40)
        {
            uint8_t fromCid = pos.y & 0x0F;
            uint8_t slot = pos.z;

            Container* parentcontainer = player->getContainer(fromCid);
            if(!parentcontainer)
                return NULL;

            return parentcontainer->getItem(slot);
        }
        else if(pos.y == 0 && pos.z == 0)
        {
            const ItemType& it = Item::items.getItemIdByClientId(spriteId);
            if(it.id == 0)
                return NULL;

            int32_t subType = -1;
            if(it.isFluidContainer())
            {
                int32_t maxFluidType = sizeof(reverseFluidMap) / sizeof(uint32_t);
                if(index < maxFluidType)
                    subType = reverseFluidMap[index];
            }
            return findItemOfType(player, it.id, true, subType);
        }
        //inventory
        else
        {
            slots_t slot = (slots_t)static_cast<unsigned char>(pos.y);
            return player->getInventoryItem(slot);
        }
    }
    return NULL;
}

@otclient
Copy link

It's different function than mine, i think instead of spamming here we should meet in skype. Gimme your skype i'll contact you soon.

@ronpetit
Copy link
Contributor Author

yeah it's, is ronpetit, same as my username here, i'm login right now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants