• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Clean SVN (before merging of revnetsys) - various weapon-related codes.

Vagabond

New Member
Joined
Oct 5, 2007
Messages
242
Reaction score
0
These codes are a small portion (which I've deemed fit to release to the general public) of a code for a project I've been planning for quite some time.
These were designed to be easy to add and configure, so it may not be the most efficient code (I haven't run any efficiency tests).
Currently, this only includes:
- Individual attack delay for weapons. This way you can have smaller, lighter weapons attacking fast and big, heavy weapons attacking slow. More realistic, and will keep people from just choosing the bigger weapon for more power. :p
- True dual wielding. Basically, you attack with one weapon and then the other. You can choose which weapons are dual wieldable by configuring them in items.xml.
- ExtraAtk for weapons/shields when used with a shield or dual wielding (don't ask why you'd need this :s)

The code:

in item.h, after:
virtual bool readAttr(AttrTypes_t attr, PropStream& propStream);
virtual bool unserializeAttr(PropStream& propStream);
virtual bool unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream);
add:
Code:
#ifdef __REVSTATS__
	bool isDualWield() const { return items[id].dualWield; }
	int getAttackSpeed() const { return items[id].atkSpeed; };
#endif
after:
int getExtraDef() const {return items[id].extraDef;}
add:
Code:
#ifdef __REVSTATS__
	int getExtraAtk() const {return items[id].extraAtk;}
#endif //__REVSTATS__
after:

in items.cpp, after:
replaceable = true;
add:
Code:
#ifdef __REVSTATS__
	dualWield = false;
	extraAtk = 0;
	atkSpeed = 2000;
#endif //__REVSTATS__
after:
else if(strcasecmp(strValue.c_str(), "attack") == 0){
if(readXMLInteger(itemAttributesNode, "value", intValue)){
it.attack = intValue;
}
}
add:
Code:
#ifdef __REVSTATS__
							else if(strcasecmp(strValue.c_str(), "extraatk") == 0){
								if(readXMLInteger(itemAttributesNode, "value", intValue)){
									it.extraAtk = intValue;
								}
							}
							else if(strcasecmp(strValue.c_str(), "dualwield") == 0){
								if(readXMLInteger(itemAttributesNode, "value", intValue)){
									it.dualWield = (intValue != 0);
								}
							}
							else if(strcasecmp(strValue.c_str(), "attackspeed") == 0){
								if(readXMLInteger(itemAttributesNode, "value", intValue)){
									it.atkSpeed = (intValue > 100) ? intValue : 2000;
								}
							}
#endif //__REVSTATS__

in items.h, after:
bool replaceable;
add:
Code:
#ifdef __REVSTATS__
	bool dualWield;
	int extraAtk;
	int atkSpeed;
#endif //__REVSTATS__


in player.cpp, after:
#ifdef __SKULLSYSTEM__
redSkullTicks = 0;
skull = SKULL_NONE;
#endif
add:
Code:
#ifdef __REVSTATS__
    nextWeapon = NULL;
#endif //__REVSTATS__
replace:
Item* Player::getWeapon()
{
Item* item;

for(uint32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
item = getInventoryItem((slots_t)slot);
if(!item){
continue;
}

switch(item->getWeaponType()){
case WEAPON_SWORD:
case WEAPON_AXE:
case WEAPON_CLUB:
case WEAPON_WAND:
{
const Weapon* weapon = g_weapons->getWeapon(item);
if(weapon){
return item;
}

break;
}

case WEAPON_DIST:
{
if(item->getAmuType() != AMMO_NONE){
Item* ammuItem = getInventoryItem(SLOT_AMMO);

if(ammuItem && ammuItem->getAmuType() == item->getAmuType()){
const Weapon* weapon = g_weapons->getWeapon(ammuItem);
if(weapon){
shootRange = item->getShootRange();
return ammuItem;
}
}
}
else{
const Weapon* weapon = g_weapons->getWeapon(item);
if(weapon){
return item;
}
}
}

default:
break;
}
}

return NULL;
}
with:
Code:
Item* Player::getWeapon()
{
	#ifndef __REVSTATS__
    Item* item;

	for(uint32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
		item = getInventoryItem((slots_t)slot);
		if(!item){
			continue;
		}

		switch(item->getWeaponType()){
			case WEAPON_SWORD:
			case WEAPON_AXE:
			case WEAPON_CLUB:
			case WEAPON_WAND:
			{
				const Weapon* weapon = g_weapons->getWeapon(item);
				if(weapon){
					return item;
				}

				break;
			}

			case WEAPON_DIST:
			{
				if(item->getAmuType() != AMMO_NONE){
					Item* ammuItem = getInventoryItem(SLOT_AMMO);

					if(ammuItem && ammuItem->getAmuType() == item->getAmuType()){
						const Weapon* weapon = g_weapons->getWeapon(ammuItem);
						if(weapon){
							shootRange = item->getShootRange();
							return ammuItem;
						}
					}
				}
				else{
					const Weapon* weapon = g_weapons->getWeapon(item);
					if(weapon){
						return item;
					}
				}
			}

			default:
				break;
		}
	}

	return NULL;
#else
	return nextWeapon;
#endif //__REVSTATS__
}
replace:
void Player::getShieldAndWeapon(const Item* &shield, const Item* &weapon) const
{
Item* item;
shield = NULL;
weapon = NULL;
for(uint32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
item = getInventoryItem((slots_t)slot);
if(item){
switch(item->getWeaponType()){
case WEAPON_NONE:
break;
case WEAPON_SHIELD:
shield = item;
break;
default: // weapons that are not shields
weapon = item;
break;
}
}
}
return;
}
with:
Code:
void Player::getShieldAndWeapon(const Item* &shield, const Item* &weapon) const
{
    #ifndef __REVSTATS__
	Item* item;
	shield = NULL;
	weapon = NULL;
	for(uint32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
		item = getInventoryItem((slots_t)slot);
		if(item){
			switch(item->getWeaponType()){
			case WEAPON_NONE:
				break;
			case WEAPON_SHIELD:
				shield = item;
				break;
			default: // weapons that are not shields
				weapon = item;
				break;
			}
		}
	}
#else
	shield = (nextWeapon == getWeaponLeft()) ? getWeaponRight() : getWeaponLeft();
	weapon = nextWeapon;
#endif
	return;
}
after:
void Player::eek:nRemoveInventoryItem(slots_t slot, Item* item)
{
//setItemAbility(slot, false);

if(tradeState != TRADE_TRANSFER){
checkTradeState(item);

if(tradeItem){
const Container* container = item->getContainer();
if(container && container->isHoldingItem(tradeItem)){
g_game.playerCloseTrade(this);
}
}
}
(note: at the end of the function) add:
Code:
#ifdef __REVSTATS__
	if(item == nextWeapon)
	{
	   nextWeapon = NULL;
       findNextWeapon();
       attackTicks = getAttackSpeed();
    }
#endif //__REVSTATS__
replace:
else if(item != inventory[SLOT_LEFT] && inventory[SLOT_LEFT]->isWeapon() &&
(inventory[SLOT_LEFT]->getWeaponType() != WEAPON_SHIELD) &&
(inventory[SLOT_LEFT]->getWeaponType() != WEAPON_AMMO) &&
item->isWeapon() && (item->getWeaponType() != WEAPON_SHIELD) && (item->getWeaponType() != WEAPON_AMMO)){
ret = RET_CANONLYUSEONEWEAPON;
with:
Code:
#ifndef __REVSTATS__
						else if(item != inventory[SLOT_LEFT] && inventory[SLOT_LEFT]->isWeapon() &&
							(inventory[SLOT_LEFT]->getWeaponType() != WEAPON_SHIELD) &&
							(inventory[SLOT_LEFT]->getWeaponType() != WEAPON_AMMO) &&
							item->isWeapon() && (item->getWeaponType() != WEAPON_SHIELD) && (item->getWeaponType() != WEAPON_AMMO)){
								ret = RET_CANONLYUSEONEWEAPON;
#else
						else if(item != inventory[SLOT_LEFT])
						{
                            Item* i = getWeaponLeft();
                            if(i && !(i->isDualWield() || i->getWeaponType() == WEAPON_SHIELD || i->getWeaponType() == WEAPON_AMMO))
                               ret = RET_CANONLYUSEONEWEAPON;
                            else
                               ret = RET_NOERROR;
                        }
#endif
replace:
else if(item != inventory[SLOT_RIGHT] && inventory[SLOT_RIGHT]->isWeapon() &&
(inventory[SLOT_RIGHT]->getWeaponType() != WEAPON_SHIELD) &&
(inventory[SLOT_RIGHT]->getWeaponType() != WEAPON_AMMO) &&
item->isWeapon() && (item->getWeaponType() != WEAPON_SHIELD) && (item->getWeaponType() != WEAPON_AMMO)){
ret = RET_CANONLYUSEONEWEAPON;
}
with:
Code:
#ifndef __REVSTATS__
						else if(item != inventory[SLOT_RIGHT] && inventory[SLOT_RIGHT]->isWeapon() &&
							(inventory[SLOT_RIGHT]->getWeaponType() != WEAPON_SHIELD) &&
							(inventory[SLOT_RIGHT]->getWeaponType() != WEAPON_AMMO) &&
							item->isWeapon() && (item->getWeaponType() != WEAPON_SHIELD) && (item->getWeaponType() != WEAPON_AMMO)){
								ret = RET_CANONLYUSEONEWEAPON;
						}
#else
						else if(item != inventory[SLOT_RIGHT])
						{
                            Item* i = getWeaponRight();
                            if(i && !(i->isDualWield() || i->getWeaponType() == WEAPON_SHIELD || i->getWeaponType() == WEAPON_AMMO))
                               ret = RET_CANONLYUSEONEWEAPON;
                            else
                               ret = RET_NOERROR;
                        }
#endif
replace:
uint32_t Player::getAttackSpeed()
{
return 2000;
}
with:
Code:
uint32_t Player::getAttackSpeed()
{
#ifndef __REVSTATS__
	return 2000;
#else
	return nextWeapon?nextWeapon->getAttackSpeed():2000; //todo: individual weapon speeds
#endif //__REVSTATS__
}
after:
if(weapon && weapon->checkLastAction(this, 100)){
attackTicks = 0;
result = weapon->useWeapon(this, tool, attackedCreature);
}
else
{
attackTicks = 0;
result = Weapon::useFist(this, attackedCreature);
}
add:
Code:
#ifdef __REVSTATS__
		findNextWeapon();
#endif
at the bottom:
Code:
#ifdef __REVSTATS__
Item* Player::getWeaponLeft() const
{
     Item* item = inventory[SLOT_LEFT];
     if(item){
		 switch(item->getWeaponType()){
			case WEAPON_NONE: case WEAPON_AMMO:
				break;
			default:
				return item;
				break;
         }
     }
     return NULL;
}
Item* Player::getWeaponRight() const
{
     Item* item = inventory[SLOT_RIGHT];
     if(item){
		 switch(item->getWeaponType()){
			case WEAPON_NONE: case WEAPON_AMMO:
				break;
			default:
				return item;
				break;
         }
     }
     return NULL;
}

void Player::findNextWeapon()
{
     Item* left = getWeaponLeft();
     Item* right = getWeaponRight();
     if(nextWeapon == left || !left || left->getWeaponType() == WEAPON_SHIELD)
        nextWeapon = right;
     else if(nextWeapon == right || !right || right->getWeaponType() == WEAPON_SHIELD)
        nextWeapon = left;
     else
        nextWeapon = NULL;
}

int32_t Player::getAttack() const
{
    int32_t attack = 0;
	int32_t extraAtk = 0;
	int32_t defenseSkill = 0;
	const Item* weapon;
	const Item* shield;
	getShieldAndWeapon(shield, weapon);

	if(weapon){
		attack = weapon->getAttack();
	}
	if(weapon && shield)
	    extraAtk = shield->getExtraAtk();
	if(shield && shield->getAttack() >= attack){
		attack = shield->getAttack() + extraAtk;
	}

	return attack;
}
#endif //__REVSTATS__


in player.h, after:
uint32_t lossPercent[LOSS_LAST + 1];
add:
Code:
#ifdef __REVSTATS__
	Item* nextWeapon;
	void findNextWeapon();
	Item* getWeaponLeft() const;
	Item* getWeaponRight() const;
	int32_t getAttack() const;
#endif //__REVSTATS__

in weapons.cpp(WeaponMelee::getWeaponDamage), replace:
int32_t attackValue = item->getAttack();
with:
Code:
#ifndef __REVSTATS__
	int32_t attackValue = item->getAttack();
#else
	int32_t attackValue = player->getAttack();
#endif //__REVSTATS__

add -D__REVSTATS__ to C++ compiler and rebuild all.




Notes:
- Never tested extraAtk. Should work, but no guarantees.
- extraAtk doesn't currently show up in item description. Forgot to do this, too lazy to do it now.
- I was moving around my weapons trying to crash it and it didn't bug or crash, so I assume the dual wielding portion of the code has no bugs. If you do find any, tell me.

Configuring items:
- To make any (one-handed) weapon dual-wieldable, edit items.xml and add the tag:
HTML:
<attribute key="dualwield" value="1" />
in the item's tag.
- To give any one-handed weapon extra attack, edit items.xml and add the tag:
HTML:
<attribute key="extraatk" value="1" />
, replacing 1 for whatever you want the extra attack to be.
- To give any one-handed weapon a custom attack delay, edit items.xml and add the tag:
HTML:
<attribute key="attackspeed" value="1500" />
, replacing 1500 for whatever you want the delay to be. (don't change it to lower than 100 it won't work)
 
Last edited:
Reputation
Your reputation on this post is Extremely Negative.
Comments on this Post
This sux Revnetsys Rox
Good Release!
You have -39 Reputation point(s).
For that noob who somehow gave me 40 points of bad rep, this should work on revnetsys servers. It is simply that I made this before revnetsys was finished, and haven't had time to test it. But yeah, thanks for being a noob and giving me bad rep over nothing. -.-
 
can't find
player.cpp
uint32_t Player::getAttackSpeed()
{
return 2000;
}
and in player.h
uint32_t lossPercent[LOSS_LAST + 1];

=/
tfs sources (18/11)
and ty.. good idea
 
Last edited:
Actually, the dual-wielding code is very bugged, I don't suggest using this code until I fix it.

TFS has changed sources a bit too much, so I can't guarantee any of my codes to work for TFS even if there is no problem adding them. :p
 
Back
Top