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

fix: weapons, reverting some changes from XML pr #784

Merged
merged 9 commits into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/creatures/combat/spells.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,11 @@ CombatSpell::CombatSpell(Combat* newCombat, bool newNeedTarget, bool needDirecti
// Empty
}

CombatSpell::~CombatSpell() = default;
CombatSpell::~CombatSpell() {
if (!isLoadedCallback()) {
delete combat;
}
}

bool CombatSpell::loadScriptCombat()
{
Expand Down
80 changes: 58 additions & 22 deletions src/items/weapons/weapons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,34 +183,40 @@ bool Weapon::useFist(Player* player, Creature* target)

void Weapon::internalUseWeapon(Player* player, Item* item, Creature* target, int32_t damageModifier) const
{
CombatDamage damage;
WeaponType_t weaponType = item->getWeaponType();
if (weaponType == WEAPON_AMMO || weaponType == WEAPON_DISTANCE) {
damage.origin = ORIGIN_RANGED;
} else {
damage.origin = ORIGIN_MELEE;
}

damage.primary.type = params.combatType;
damage.secondary.type = getElementType();

if (damage.secondary.type == COMBAT_NONE) {
damage.primary.value = (getWeaponDamage(player, target, item) * damageModifier) / 100;
damage.secondary.value = 0;
if (isLoadedCallback()) {
LuaVariant var;
var.type = VARIANT_NUMBER;
var.number = target->getID();
executeUseWeapon(player, var);
} else {
CombatDamage damage;
WeaponType_t weaponType = item->getWeaponType();
if (weaponType == WEAPON_AMMO || weaponType == WEAPON_DISTANCE) {
damage.origin = ORIGIN_RANGED;
} else {
damage.origin = ORIGIN_MELEE;
}
damage.primary.type = params.combatType;
damage.primary.value = (getWeaponDamage(player, target, item) * damageModifier) / 100;
damage.secondary.value = (getElementDamage(player, target, item) * damageModifier) / 100;
damage.secondary.type = getElementType();
damage.secondary.value = getElementDamage(player, target, item);
Combat::doCombatHealth(player, target, damage, params);
}

Combat::doCombatHealth(player, target, damage, params);

onUsedWeapon(player, item, target->getTile());
}

void Weapon::internalUseWeapon(Player* player, Item* item, Tile* tile) const
{
Combat::postCombatEffects(player, tile->getPosition(), params);
g_game().addMagicEffect(tile->getPosition(), CONST_ME_POFF);
if (isLoadedCallback()) {
LuaVariant var;
var.type = VARIANT_TARGETPOSITION;
var.pos = tile->getPosition();
executeUseWeapon(player, var);
} else {
Combat::postCombatEffects(player, tile->getPosition(), params);
g_game().addMagicEffect(tile->getPosition(), CONST_ME_POFF);
}
onUsedWeapon(player, item, tile);
}

Expand Down Expand Up @@ -295,6 +301,29 @@ int32_t Weapon::getHealthCost(const Player* player) const
return (player->getMaxHealth() * healthPercent) / 100;
}

bool Weapon::executeUseWeapon(Player* player, const LuaVariant& var) const
{
//onUseWeapon(player, var)
if (!getScriptInterface()->reserveScriptEnv()) {
SPDLOG_ERROR("[Weapon::executeUseWeapon - Player {} weaponId {}]"
"Call stack overflow. Too many lua script calls being nested.",
player->getName(), getID());
return false;
}

ScriptEnvironment* env = getScriptInterface()->getScriptEnv();
env->setScriptId(getScriptId(), getScriptInterface());

lua_State* L = getScriptInterface()->getLuaState();

getScriptInterface()->pushFunction(getScriptId());
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
getScriptInterface()->pushVariant(L, var);

return getScriptInterface()->callFunction(2);
}

void Weapon::decrementItemCount(Item* item)
{
uint16_t count = item->getItemCount();
Expand All @@ -305,13 +334,16 @@ void Weapon::decrementItemCount(Item* item)
}
}

void WeaponMelee::configureWeapon(const ItemType& it)
WeaponMelee::WeaponMelee(LuaScriptInterface* interface) : Weapon(interface)
{
// Add combat type and blocked attributes to the weapon
params.blockedByArmor = true;
params.blockedByShield = true;
params.combatType = COMBAT_PHYSICALDAMAGE;
}

void WeaponMelee::configureWeapon(const ItemType& it)
{
if (it.abilities) {
elementType = it.abilities->elementType;
elementDamage = it.abilities->elementDamage;
Expand Down Expand Up @@ -407,13 +439,17 @@ int32_t WeaponMelee::getWeaponDamage(const Player* player, const Creature*, cons
return -normal_random(minValue, (maxValue * static_cast<int32_t>(player->getVocation()->meleeDamageMultiplier)));
}

void WeaponDistance::configureWeapon(const ItemType& it)
WeaponDistance::WeaponDistance(LuaScriptInterface* interface) :
Weapon(interface)
{
// Add combat type and distance effect to the weapon
params.blockedByArmor = true;
params.combatType = COMBAT_PHYSICALDAMAGE;
params.distanceEffect = it.shootType;
}

void WeaponDistance::configureWeapon(const ItemType& it)
{
params.distanceEffect = it.shootType;
if (it.abilities) {
elementType = it.abilities->elementType;
elementDamage = it.abilities->elementDamage;
Expand Down
25 changes: 22 additions & 3 deletions src/items/weapons/weapons.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ class Weapons final : public Scripts

constexpr auto g_weapons = &Weapons::getInstance;

class Weapon
class Weapon : public Script
{
public:
Weapon() = default;
virtual ~Weapon() = default;
explicit Weapon(LuaScriptInterface* interface) : Script(interface) {}

virtual void configureWeapon(const ItemType& it);
virtual bool interruptSwing() const {
return false;
Expand Down Expand Up @@ -191,6 +191,7 @@ class Weapon

uint32_t getManaCost(const Player* player) const;
int32_t getHealthCost(const Player* player) const;
bool executeUseWeapon(Player* player, const LuaVariant& var) const;

uint16_t id = 0;

Expand Down Expand Up @@ -227,6 +228,12 @@ class Weapon
class WeaponMelee final : public Weapon
{
public:
explicit WeaponMelee(LuaScriptInterface* interface);

std::string getScriptTypeName() const override {
return "onUseWeapon";
}

void configureWeapon(const ItemType& it) override;

bool useWeapon(Player* player, Item* item, Creature* target) const override;
Expand All @@ -246,6 +253,12 @@ class WeaponMelee final : public Weapon
class WeaponDistance final : public Weapon
{
public:
explicit WeaponDistance(LuaScriptInterface* interface);

std::string getScriptTypeName() const override {
return "onUseWeapon";
}

void configureWeapon(const ItemType& it) override;
bool interruptSwing() const override {
return true;
Expand All @@ -267,6 +280,12 @@ class WeaponDistance final : public Weapon
class WeaponWand final : public Weapon
{
public:
explicit WeaponWand(LuaScriptInterface* interface) : Weapon(interface) {}

std::string getScriptTypeName() const override {
return "onUseWeapon";
}

void configureWeapon(const ItemType& it) override;

int32_t getWeaponDamage(const Player* player, const Creature* target, const Item* item, bool maxDamage = false) const override;
Expand Down
14 changes: 10 additions & 4 deletions src/lua/functions/items/weapon_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ int WeaponFunctions::luaCreateWeapon(lua_State* L) {
case WEAPON_SWORD:
case WEAPON_AXE:
case WEAPON_CLUB: {
auto weapon = new WeaponMelee();
WeaponMelee* weapon = new WeaponMelee(getScriptEnv()->getScriptInterface());
if (weapon) {
pushUserdata<WeaponMelee>(L, weapon);
setMetatable(L, -1, "Weapon");
Expand All @@ -35,7 +35,7 @@ int WeaponFunctions::luaCreateWeapon(lua_State* L) {
}
case WEAPON_DISTANCE:
case WEAPON_AMMO: {
auto weapon = new WeaponDistance();
WeaponDistance* weapon = new WeaponDistance(getScriptEnv()->getScriptInterface());
if (weapon) {
pushUserdata<WeaponDistance>(L, weapon);
setMetatable(L, -1, "Weapon");
Expand All @@ -46,7 +46,7 @@ int WeaponFunctions::luaCreateWeapon(lua_State* L) {
break;
}
case WEAPON_WAND: {
auto weapon = new WeaponWand();
WeaponWand* weapon = new WeaponWand(getScriptEnv()->getScriptInterface());
if (weapon) {
pushUserdata<WeaponWand>(L, weapon);
setMetatable(L, -1, "Weapon");
Expand Down Expand Up @@ -113,6 +113,7 @@ int WeaponFunctions::luaWeaponRegister(lua_State* L) {
}

weapon->configureWeapon(it);
weapon->setLoadedCallback(true);
pushBoolean(L, g_weapons().registerLuaEvent(weapon));
weapon = nullptr; // Releases weapon, removing the luascript reference
} else {
Expand All @@ -123,8 +124,13 @@ int WeaponFunctions::luaWeaponRegister(lua_State* L) {

int WeaponFunctions::luaWeaponOnUseWeapon(lua_State* L) {
// weapon:onUseWeapon(callback)
const Weapon* weapon = getUserdata<Weapon>(L, 1);
Weapon* weapon = getUserdata<Weapon>(L, 1);
if (weapon) {
if (!weapon->loadCallback()) {
pushBoolean(L, false);
return 1;
}

pushBoolean(L, true);
} else {
lua_pushnil(L);
Expand Down