C++ Quiver for Nostalrius 7.7

Sequax

Member
Joined
Oct 24, 2008
Messages
19
Best answers
0
Reaction score
5
Hey, been trying to figure out how to get a quiver to work on Nostalrius 7.7.

Here the git for the sources I'm using: GitHub

I've tried looking at these two tutorials but my players.cpp doesn't match. I don't have any "ammoItem".
Quiver [TFS 1.X + 0.X]
Quiver for paladins - tfs1.X

I don't know that much about coding, I usually just look at what other people have done and try to figure out the patterns, but in this case, I see none. I can find places where it says AMMO_NONE in different files just as the tutorials, but it always comes down to "ammoItem" which is missing for me.

For the record I'm not particularly interested in setting a limit as said in the first tutorial.

Any ideas? Would be much appreciated.

Here's what I've found that seems kind of similar:

player.cpp
C++:
Item* Player::getAmmunition() const
{
return inventory[CONST_SLOT_AMMO];
}
item.cpp
C++:
    } else if (it.weaponType != WEAPON_NONE) {
        if (it.weaponType == WEAPON_DISTANCE && it.ammoType != AMMO_NONE) {
            if (it.attack != 0) {
                s << ", Atk" << std::showpos << it.attack << std::noshowpos;
            }
        } else if (it.weaponType != WEAPON_AMMO && it.weaponType != WEAPON_WAND && (it.attack != 0 || it.defense != 0)) {
            s << " (";
            if (it.attack != 0) {
                s << "Atk:" << static_cast<int>(it.attack);
            }

            if (it.defense != 0) {
                if (it.attack != 0)
                    s << " ";
combat.cpp
C++:
        if (weapon->getWeaponType() == WEAPON_DISTANCE) {
            ammunition = player->getAmmunition();
            if (weapon->getAmmoType() != AMMO_NONE) {
                if (!ammunition || weapon->getAmmoType() != ammunition->getAmmoType()) {
                    // redirect to fist fighting
                    return closeAttack(attacker, target, fightMode);
                }
C++:
                if (weapon->getAmmoType() != AMMO_NONE) {
                    Item* ammunition = player->getAmmunition();
                    if (ammunition && ammunition->getAmmoType() == weapon->getAmmoType()) {
                        attackValue += ammunition->getAttack();
                    }
                }
C++:
        if (ammunition && weapon->getAmmoType() != AMMO_NONE && weapon->getAmmoType() == ammunition->getAmmoType()) {
            hitChance = 90; // bows and crossbows
            specialEffect = ammunition->getWeaponSpecialEffect();
            attackStrength = ammunition->getAttackStrength();
            attackVariation = ammunition->getAttackVariation();
            if (normal_random(0, 100) <= ammunition->getFragility()) {
                uint16_t count = ammunition->getItemCount();
                if (count > 1) {
                    g_game.transformItem(ammunition, ammunition->getID(), count - 1);
                } else {
                    g_game.internalRemoveItem(ammunition);
                }
            }

            moveWeapon = false;
        }
items.cpp
C++:
                        items[id].ammoType = getAmmoType(script.readIdentifier());
                        if (items[id].ammoType == AMMO_NONE) {
                            script.error("Unknown ammo type");
                            return false;
 

Discovery

Developing myself
Joined
Apr 16, 2010
Messages
451
Best answers
7
Reaction score
130
Location
Neverland
I developed a quiver for it, my tip is: try to make a new flag, like itemType = quiver.

Its more easily to organize.
1568635721122.png
1568635755774.png
1568635917500.png
ps:
wtff...
thats a active member

1568635590245.png
 
OP
Sequax

Sequax

Member
Joined
Oct 24, 2008
Messages
19
Best answers
0
Reaction score
5
Thanks for the input. I have a few questions however, because this doesn't really make sense to me.

So it looks like in your first pic you just added that line in items.cpp, that's pretty straight forward. But then I don't really understand where the code in your second pic should go. Is it in items.h? I tried to compile with it and got this error:

C++:
In file included from /XXX/item.h:25,
                 from /XXX/bed.h:23,
                 from /XXX/actions.cpp:23:
/XXX/items.h: In member function ‘bool ItemType::isQuiver() const’:
/XXX/items.h:131:11: error: ‘items’ was not declared in this scope
    return items[id].isQuiver();
/XXX/items.h:131:11: note: suggested alternative: ‘item_t’
    return items[id].isQuiver();
Now to your third pic. Is that supposed to be in player.cpp? My best guess was to put it under "Item* Player::getWeapon() const. But that was a shot in the dark really. I have absolutely no idea where that's supposed to be.

Like I said, I don't really know the coding rules or language, I just doing my best to follow the logic in other people's work, so if you don't mind, be more like "This goes here and this goes there" and such.

I really appreciate the help though!
 

Delusion

Divine Intellect
Support Team
Joined
Feb 14, 2015
Messages
5,340
Best answers
528
Reaction score
3,068
Thanks for the input. I have a few questions however, because this doesn't really make sense to me.

So it looks like in your first pic you just added that line in items.cpp, that's pretty straight forward. But then I don't really understand where the code in your second pic should go. Is it in items.h? I tried to compile with it and got this error:

C++:
In file included from /XXX/item.h:25,
                 from /XXX/bed.h:23,
                 from /XXX/actions.cpp:23:
/XXX/items.h: In member function ‘bool ItemType::isQuiver() const’:
/XXX/items.h:131:11: error: ‘items’ was not declared in this scope
    return items[id].isQuiver();
/XXX/items.h:131:11: note: suggested alternative: ‘item_t’
    return items[id].isQuiver();
Now to your third pic. Is that supposed to be in player.cpp? My best guess was to put it under "Item* Player::getWeapon() const. But that was a shot in the dark really. I have absolutely no idea where that's supposed to be.

Like I said, I don't really know the coding rules or language, I just doing my best to follow the logic in other people's work, so if you don't mind, be more like "This goes here and this goes there" and such.

I really appreciate the help though!
item.h, inside of class Item underneath where all other methods use items[id], use ctrl+f to find it.
 
OP
Sequax

Sequax

Member
Joined
Oct 24, 2008
Messages
19
Best answers
0
Reaction score
5
Alrigth so here's what I've done so far:

in item.h I just add this (line 714):
C++:
        bool isQuiver() const {
            return items[id].isQuiver();
in items.cpp I add (line 116)
C++:
else if (identifier == "quiver") {
                        items[id].group = ITEM_GROUP_QUIVER;
                    }
in player.cpp(line 180) i add
C++:
    if (Item* cylinderItem = toCylinder->getItem()){
        if (cylinderItem->isQuiver() && item->getWeaponType() != WEAPON_AMMO){
            Player* player = actor->getPlayer();
            if(player){
                std::ostringstream ss;
                ss << "Only ammunition accepted in that container.";
                player->sendCancelMessage(ss.str());
                    return ret;
            }
        }
    }
in items.h I add (line 166)
C++:
        bool isQuiver() const {
            return type == ITEM_TYPE_QUIVER;
Also in items.h (line 57)
C++:
    ITEM_TYPE_QUIVER,
also in items.h (line 77)
C++:
GROUP_TYPE_QUIVER,
At first a was stuggeling a bit with the item.h / items.cpp, but after a while I stopped getting errors. However with player.cpp I can't seem to find a solution. I keep getting error about toCylinder. I messed around with it quite a bit, but I really can't figure it out. This is the error I get when I try to compile it.

Code:
/XXX/player.cpp: In member function ‘Item* Player::getWeapon() const’:
/XXX/player.cpp:180:27: error: ‘toCylinder’ was not declared in this scope
  if (Item* cylinderItem = toCylinder->getItem()){
/XXX/player.cpp:180:27: note: suggested alternative: ‘Cylinder’
  if (Item* cylinderItem = Cylinder->getItem()){
/XXX/player.cpp:182:21: error: ‘actor’ was not declared in this scope
    Player* player = actor->getPlayer();
/XXX/player.cpp:182:21: note: suggested alternative: ‘wctob’
    Player* player = wctob->getPlayer();
/XXX/player.cpp:187:13: error: ‘ret’ was not declared in this scope
      return ret;
Any ideas?

Here's my full files if you want to check for reference (pastebin):

items.h
items.cpp
item.h
player.cpp
 

leleco95

Member
Joined
May 6, 2009
Messages
23
Best answers
4
Reaction score
24
I can't help you much, only explain some things

in player.cpp(line 180) i add
C++:
    if (Item* cylinderItem = toCylinder->getItem()){
        if (cylinderItem->isQuiver() && item->getWeaponType() != WEAPON_AMMO){
            Player* player = actor->getPlayer();
            if(player){
                std::ostringstream ss;
                ss << "Only ammunition accepted in that container.";
                player->sendCancelMessage(ss.str());
                    return ret;
            }
        }
    }
That's because it doesn't belong there. As you can see, it sends a message saying that "Only ammunition is accepted in that container", so it has something to do with moving items to the quiver. Also, the errors indicate that variables "toCylinder" and "actor" do not exist.

About the getWeapon function, it seems that your source's function has been changed in relation to the original TFS

So when comparing the two example quivers you linked, you should probably do something inside getAmmunition to loop the quiver and find its ammos if the slot item isn't ammunition (similar to how they do).

I hope this helps you.

-- EDIT

I have not tested and can't, but your getAmmunition function should be something like this, I think:

C++:
Item* Player::getAmmunition() const
{
    Item* item = inventory[CONST_SLOT_AMMO];
    if(!item)
        return nullptr;

    if(Container *container = item->getContainer()) {
        Item* weapon = getWeapon();
        const ItemType& it = Item::items[weapon->getID()];
        for(ContainerIterator iter = container->iterator(); iter.hasNext(); iter.advance()) {
            const ItemType& itr = Item::items[(*iter)->getID()];
            if(itr.ammoType == it.ammoType)
                return (*iter);
        }
    }

    return item;
}
 
Last edited:
OP
Sequax

Sequax

Member
Joined
Oct 24, 2008
Messages
19
Best answers
0
Reaction score
5
Hey thanks, I will definitly look into this!
 
OP
Sequax

Sequax

Member
Joined
Oct 24, 2008
Messages
19
Best answers
0
Reaction score
5
C++:
Item* Player::getAmmunition() const
{
    Item* item = inventory[CONST_SLOT_AMMO];
    if(!item)
        return nullptr;

    if(Container *container = item->getContainer()) {
        Item* weapon = getWeapon();
        const ItemType& it = Item::items[weapon->getID()];
        for(ContainerIterator iter = container->iterator(); iter.hasNext(); iter.advance()) {
            const ItemType& itr = Item::items[(*iter)->getID()];
            if(itr.ammoType == it.ammoType)
                return (*iter);
        }
    }

    return item;
}
I can't beleive it. It actually worked! No errors or anything!

Thank you so much! You have no idea how many hours I spent trying to solve this haha
 
Top