CombatDamage Combat::getCombatDamage(Creature* creature, Creature* target) const
{
	CombatDamage damage;
	damage.origin = params.origin;
	damage.primary.type = params.combatType;
	if (formulaType == COMBAT_FORMULA_DAMAGE) {
		damage.primary.value = normal_random(
			static_cast<int32_t>(mina),
			static_cast<int32_t>(maxa)
		);
	} else if (creature) {
		int32_t min, max;
		if (creature->getCombatValues(min, max)) {
			damage.primary.value = normal_random(min, max);
		} else if (Player* player = creature->getPlayer()) {
			if (params.valueCallback) {
				params.valueCallback->getMinMaxValues(player, damage, params.useCharges);
			} else if (formulaType == COMBAT_FORMULA_LEVELMAGIC) {
				int32_t levelFormula = player->getLevel() * 2 + player->getMagicLevel() * 3;
				damage.primary.value = normal_random(
					static_cast<int32_t>(levelFormula * mina + minb),
					static_cast<int32_t>(levelFormula * maxa + maxb)
				);
			} else if (formulaType == COMBAT_FORMULA_SKILL) {
				Item* tool = player->getWeapon();
				const Weapon* weapon = g_weapons->getWeapon(tool);
				if (weapon) {
					damage.primary.value = normal_random(
						static_cast<int32_t>(minb),
						static_cast<int32_t>(weapon->getWeaponDamage(player, target, tool, true) * maxa + maxb)
					);

					damage.secondary.type = weapon->getElementType();
					damage.secondary.value = weapon->getElementDamage(player, target, tool);
					if (params.useCharges) {
						uint16_t charges = tool->getCharges();
						if (charges != 0) {
							g_game.transformItem(tool, tool->getID(), charges - 1);
						}
					}
				} else {
					damage.primary.value = normal_random(
						static_cast<int32_t>(minb),
						static_cast<int32_t>(maxb)
					);
				}
			}
		}
	}
	return damage;
}
Example #2
0
void ValueCallback::getMinMaxValues(Player* player, CombatDamage& damage, bool useCharges) const
{
	//"onGetPlayerMinMaxValues"(...)
	if (!m_scriptInterface->reserveScriptEnv()) {
		std::cout << "[Error - ValueCallback::getMinMaxValues] Call stack overflow" << std::endl;
		return;
	}

	ScriptEnvironment* env = m_scriptInterface->getScriptEnv();
	if (!env->setCallbackId(m_scriptId, m_scriptInterface)) {
		m_scriptInterface->resetScriptEnv();
		return;
	}

	lua_State* L = m_scriptInterface->getLuaState();

	m_scriptInterface->pushFunction(m_scriptId);
	lua_pushnumber(L, player->getID());

	int32_t parameters = 1;
	switch (type) {
		case COMBAT_FORMULA_LEVELMAGIC: {
			//"onGetPlayerMinMaxValues"(cid, level, maglevel)
			lua_pushnumber(L, player->getLevel());
			lua_pushnumber(L, player->getMagicLevel());
			parameters += 2;
			break;
		}

		case COMBAT_FORMULA_SKILL: {
			//"onGetPlayerMinMaxValues"(cid, attackSkill, attackValue, attackFactor)
			Item* tool = player->getWeapon();
			const Weapon* weapon = g_weapons->getWeapon(tool);

			int32_t attackValue = 7;
			if (weapon) {
				attackValue = tool->getAttack();

				damage.secondary.type = weapon->getElementType();
				damage.secondary.value = weapon->getElementDamage(player, nullptr, tool);
				if (useCharges) {
					uint16_t charges = tool->getCharges();
					if (charges != 0) {
						g_game.transformItem(tool, tool->getID(), charges - 1);
					}
				}
			}

			lua_pushnumber(L, player->getWeaponSkill(tool));
			lua_pushnumber(L, attackValue);
			lua_pushnumber(L, player->getAttackFactor());
			parameters += 3;
			break;
		}

		default: {
			std::cout << "ValueCallback::getMinMaxValues - unknown callback type" << std::endl;
			m_scriptInterface->resetScriptEnv();
			return;
		}
	}

	int32_t size0 = lua_gettop(L);
	if (lua_pcall(L, parameters, 2, 0) != 0) {
		LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
	} else {
		damage.primary.value = normal_random(
			LuaScriptInterface::getNumber<int32_t>(L, -2),
			LuaScriptInterface::getNumber<int32_t>(L, -1)
		);
		lua_pop(L, 2);
	}

	if ((lua_gettop(L) + parameters + 1) != size0) {
		LuaScriptInterface::reportError(nullptr, "Stack size changed!");
	}

	m_scriptInterface->resetScriptEnv();
}
Example #3
0
bool Combat::getMinMaxValues(Creature* creature, Creature* target, int32_t& min, int32_t& max) const
{
	if(!creature)
		return false;

	if(creature->getCombatValues(min, max))
		return true;
	else if(Player* player = creature->getPlayer())
	{
		if(params.valueCallback)
		{
			params.valueCallback->getMinMaxValues(player, min, max, params.useCharges);
			return true;
		}
		else
		{
			switch(formulaType)
			{
				case FORMULA_LEVELMAGIC:
				{
					max = (int32_t)((player->getLevel() * 2 + player->getMagicLevel() * 3) * 1. * mina + minb);
					min = (int32_t)((player->getLevel() * 2 + player->getMagicLevel() * 3) * 1. * maxa + maxb);
					return true;
				}

				case FORMULA_SKILL:
				{
					Item* tool = player->getWeapon();
					const Weapon* weapon = g_weapons->getWeapon(tool);

					min = (int32_t)minb;
					if(weapon)
					{
						max = (int32_t)(weapon->getWeaponDamage(player, target, tool, true) * maxa + maxb);
						if(params.useCharges && tool->hasCharges())
						{
							int32_t newCharge = std::max((int32_t)0, ((int32_t)tool->getCharges()) - 1);
							g_game.transformItem(tool, tool->getID(), newCharge);
						}
					}
					else
						max = (int32_t)maxb;

					return true;
				}

				case FORMULA_VALUE:
				{
					min = (int32_t)mina;
					max = (int32_t)maxa;
					return true;
				}

				default:
				{
					min = 0;
					max = 0;
					return false;
				}
			}
		}
	}
	else if(formulaType == FORMULA_VALUE)
	{
		min = (int32_t)mina;
		max = (int32_t)maxa;
		return true;
	}
	return false;
}
Example #4
0
void ValueCallback::getMinMaxValues(Player* player, int32_t& min, int32_t& max, bool useCharges) const
{
	//"onGetPlayerMinMaxValues"(...)
	if(m_scriptInterface->reserveScriptEnv())
	{
		ScriptEnviroment* env = m_scriptInterface->getScriptEnv();
		lua_State* L = m_scriptInterface->getLuaState();

		if(!env->setCallbackId(m_scriptId, m_scriptInterface))
			return;

		uint32_t cid = env->addThing(player);

		m_scriptInterface->pushFunction(m_scriptId);
		lua_pushnumber(L, cid);

		int32_t parameters = 1;

		switch(type)
		{
			case FORMULA_LEVELMAGIC:
			{
				//"onGetPlayerMinMaxValues"(cid, level, maglevel)
				lua_pushnumber(L, player->getLevel());
				lua_pushnumber(L, player->getMagicLevel());
				parameters += 2;
				break;
			}

			case FORMULA_SKILL:
			{
				//"onGetPlayerMinMaxValues"(cid, attackSkill, attackValue, attackFactor)
				Item* tool = player->getWeapon();
				int32_t attackSkill = player->getWeaponSkill(tool);
				int32_t attackValue = 7;
				if(tool)
				{
					attackValue = tool->getAttack();
					if(useCharges && tool->hasCharges())
					{
						int32_t newCharge = std::max(0, tool->getCharges() - 1);
						g_game.transformItem(tool, tool->getID(), newCharge);
					}
				}
				float attackFactor = player->getAttackFactor();

				lua_pushnumber(L, attackSkill);
				lua_pushnumber(L, attackValue);
				lua_pushnumber(L, attackFactor);
				parameters += 3;
				break;
			}

			default:
			{
				std::cout << "ValueCallback::getMinMaxValues - unknown callback type" << std::endl;
				return;
				break;
			}
		}

		int32_t size0 = lua_gettop(L);
		if(lua_pcall(L, parameters, 2 /*nReturnValues*/, 0) != 0)
			LuaScriptInterface::reportError(NULL, LuaScriptInterface::popString(L));
		else
		{
			max = LuaScriptInterface::popNumber(L);
			min = LuaScriptInterface::popNumber(L);
		}

		if((lua_gettop(L) + parameters /*nParams*/  + 1) != size0)
			LuaScriptInterface::reportError(NULL, "Stack size changed!");

		env->resetCallback();
		m_scriptInterface->releaseScriptEnv();
	}
	else
	{
		std::cout << "[Error] Call stack overflow. ValueCallback::getMinMaxValues" << std::endl;
		return;
	}
}
Example #5
0
bool Combat::getMinMaxValues(Creature* creature, Creature* target, int32_t& min, int32_t& max) const
{
	if(creature){
		if(creature->getCombatValues(min, max)){
			return true;
		}
		else if(Player* player = creature->getPlayer()){
			if(params.valueCallback){
				params.valueCallback->getMinMaxValues(player, min, max, params.useCharges);
				return true;
			}
			else{
				switch(formulaType){
					case FORMULA_LEVELMAGIC:
					{
						max = (int32_t)((player->getLevel() + player->getMagicLevel() * 4) * 1. * mina + minb);
						min = (int32_t)((player->getLevel() + player->getMagicLevel() * 4) * 1. * maxa + maxb);

						Vocation* vocation = player->getVocation();
						if(vocation){
							if(max > 0 && min > 0 && vocation->getHealingBaseDamage() != 1.0){
								min = int32_t(min * vocation->getHealingBaseDamage());
								max = int32_t(max * vocation->getHealingBaseDamage());
							}
							else if(max < 0 && min < 0 && vocation->getMagicBaseDamage() != 1.0){
								min = int32_t(min * vocation->getMagicBaseDamage());
								max = int32_t(max * vocation->getMagicBaseDamage());
							}
						}

						return true;
						break;
					}

					case FORMULA_SKILL:
					{
						Item* tool = player->getWeapon();
						const Weapon* weapon = g_weapons->getWeapon(tool);

						min = (int32_t)minb;

						if(weapon){
							max = (int32_t)(weapon->getWeaponDamage(player, target, tool, true) * maxa + maxb);
							if(params.useCharges && tool->hasCharges() && g_config.getNumber(ConfigManager::REMOVE_WEAPON_CHARGES)){
								int32_t newCharge = std::max((int32_t)0, ((int32_t)tool->getCharges()) - 1);
								g_game.transformItem(tool, tool->getID(), newCharge);
							}
						}
						else{
							max = (int32_t)maxb;
						}

						return true;
						break;
					}

					case FORMULA_VALUE:
					{
						min = (int32_t)mina;
						max = (int32_t)maxa;
						return true;
						break;
					}

					default:
						min = 0;
						max = 0;
						return false;
						break;
				}

				//std::cout << "No callback set for combat" << std::endl;
			}
		}
	}

	if(formulaType == FORMULA_VALUE){
		min = (int32_t)mina;
		max = (int32_t)maxa;
		return true;
	}

	return false;
}
Example #6
0
void ValueCallback::getMinMaxValues(Player* player, int32_t& min, int32_t& max, bool useCharges) const
{
	//"onGetPlayerMinMaxValues"(...)
	if(m_scriptInterface->reserveScriptEnv()){
		ScriptEnviroment* env = m_scriptInterface->getScriptEnv();
		lua_State* L = m_scriptInterface->getLuaState();

		if(!env->setCallbackId(m_scriptId, m_scriptInterface))
			return;

		uint32_t cid = env->addThing(player);

		m_scriptInterface->pushFunction(m_scriptId);
		lua_pushnumber(L, cid);

		int32_t parameters = 1;
		bool isMagicFormula = false;

		switch(type){
			case FORMULA_LEVELMAGIC:
			{
				//"onGetPlayerMinMaxValues"(cid, level, maglevel)
				lua_pushnumber(L, player->getLevel());
				lua_pushnumber(L, player->getMagicLevel());
				parameters += 2;
				isMagicFormula = true;
				break;
			}

			case FORMULA_SKILL:
			{
				//"onGetPlayerMinMaxValues"(cid, attackSkill, attackValue, attackFactor)
				Item* tool = player->getWeapon();
				int32_t attackSkill = player->getWeaponSkill(tool);
				int32_t attackValue = g_config.getNumber(ConfigManager::FIST_STRENGTH);
				if(tool){
					attackValue = tool->getAttack();

					if(useCharges && tool->hasCharges() && g_config.getNumber(ConfigManager::REMOVE_WEAPON_CHARGES)){
						int32_t newCharge = std::max(0, tool->getCharges() - 1);
						g_game.transformItem(tool, tool->getID(), newCharge);
					}
				}
				float attackFactor = player->getAttackFactor();

				lua_pushnumber(L, attackSkill);
				lua_pushnumber(L, attackValue);
				lua_pushnumber(L, attackFactor);
				parameters += 3;
				break;
			}

			default:
				std::cout << "ValueCallback::getMinMaxValues - unknown callback type" << std::endl;
				return;
				break;
		}

		int size0 = lua_gettop(L);
		if(lua_pcall(L, parameters, 2 /*nReturnValues*/, 0) != 0){
			LuaScriptInterface::reportError(NULL, LuaScriptInterface::popString(L));
		}
		else{
			max = LuaScriptInterface::popNumber(L);
			min = LuaScriptInterface::popNumber(L);

			Vocation* vocation = player->getVocation();
			if(isMagicFormula && vocation){
				if(max > 0 && min > 0 && vocation->getHealingBaseDamage() != 1.0){
					min = int32_t(min * vocation->getHealingBaseDamage());
					max = int32_t(max * vocation->getHealingBaseDamage());
				}
				else if(max < 0 && min < 0 && vocation->getMagicBaseDamage() != 1.0){
					min = int32_t(min * vocation->getMagicBaseDamage());
					max = int32_t(max * vocation->getMagicBaseDamage());
				}
			}
		}

		if((lua_gettop(L) + parameters /*nParams*/  + 1) != size0){
			LuaScriptInterface::reportError(NULL, "Stack size changed!");
		}

		env->resetCallback();
		m_scriptInterface->releaseScriptEnv();
	}
	else{
		std::cout << "[Error] Call stack overflow. ValueCallback::getMinMaxValues" << std::endl;
		return;
	}
}
Example #7
0
void ValueCallback::getMinMaxValues(Player* player, int32_t& min, int32_t& max, bool useCharges) const
{
	//"onGetPlayerMinMaxValues"(cid, ...)
	if(!m_interface->reserveEnv())
	{
		LOGe("[ValueCallback::getMinMaxValues] Callstack overflow.");
		return;
	}

	ScriptEnviroment* env = m_interface->getEnv();
	if(!env->setCallbackId(m_scriptId, m_interface))
		return;

	m_interface->pushFunction(m_scriptId);
	lua_State* L = m_interface->getState();
	lua_pushnumber(L, env->addThing(player));

	int32_t parameters = 1;
	switch(type)
	{
		case FORMULA_LEVELMAGIC:
		{
			//"onGetPlayerMinMaxValues"(cid, level, magLevel)
			lua_pushnumber(L, player->getLevel());
			lua_pushnumber(L, player->getMagicLevel());

			parameters += 2;
			break;
		}

		case FORMULA_SKILL:
		{
			//"onGetPlayerMinMaxValues"(cid, level, skill, attack, factor)
			Item* tool = player->getWeapon();
			lua_pushnumber(L, player->getLevel());
			lua_pushnumber(L, player->getWeaponSkill(tool));

			int32_t attack = 7;
			if(tool)
			{
				attack = tool->getAttack();
				if(useCharges && tool->hasCharges() && server.configManager().getBool(ConfigManager::REMOVE_WEAPON_CHARGES))
					server.game().transformItem(tool, tool->getId(), std::max(0, tool->getCharges() - 1));
			}

			lua_pushnumber(L, attack);
			lua_pushnumber(L, player->getAttackFactor());

			parameters += 4;
			break;
		}

		default:
		{
			LOGe("[ValueCallback::getMinMaxValues] Unknown callback type");
			return;
		}
	}

	int32_t params = lua_gettop(L);
	if(!lua_pcall(L, parameters, 2, 0))
	{
		min = LuaScriptInterface::popNumber(L);
		max = LuaScriptInterface::popNumber(L);
		player->increaseCombatValues(min, max, useCharges, type != FORMULA_SKILL);
	}
	else
		LuaScriptInterface::error(nullptr, std::string(LuaScriptInterface::popString(L)));

	if((lua_gettop(L) + parameters + 1) != params)
		LuaScriptInterface::error(__FUNCTION__, "Stack size changed!");

	env->resetCallback();
	m_interface->releaseEnv();
}
Example #8
0
bool Combat::getMinMaxValues(const CreatureP& creature, const CreatureP& target, int32_t& min, int32_t& max) const
{
	if(creature)
	{
		if(creature->getCombatValues(min, max))
			return true;

		if(Player* player = creature->getPlayer())
		{
			if(params.valueCallback)
			{
				params.valueCallback->getMinMaxValues(player, min, max, params.useCharges);
				return true;
			}

			min = max = 0;
			switch(formulaType)
			{
				case FORMULA_LEVELMAGIC:
				{
					min = (int32_t)((player->getLevel() / minl + player->getMagicLevel() * minm) * 1. * mina + minb);
					max = (int32_t)((player->getLevel() / maxl + player->getMagicLevel() * maxm) * 1. * maxa + maxb);
					if(minc && std::abs(min) < std::abs(minc))
						min = minc;

					if(maxc && std::abs(max) < std::abs(maxc))
						max = maxc;

					player->increaseCombatValues(min, max, params.useCharges, true);
					return true;
				}

				case FORMULA_SKILL:
				{
					Item* tool = player->getWeapon();
					if(WeaponPC weapon = server.weapons().getWeapon(tool))
					{
						max = (int32_t)(weapon->getWeaponDamage(*player, target.get(), tool, true) * maxa + maxb);
						if(params.useCharges && tool->hasCharges() && server.configManager().getBool(ConfigManager::REMOVE_WEAPON_CHARGES))
							server.game().transformItem(tool, tool->getId(), std::max((int32_t)0, ((int32_t)tool->getCharges()) - 1));
					}
					else
						max = (int32_t)maxb;

					min = (int32_t)minb;
					if(maxc && std::abs(max) < std::abs(maxc))
						max = maxc;

					return true;
				}

				case FORMULA_VALUE:
				{
					min = (int32_t)minb;
					max = (int32_t)maxb;
					return true;
				}

				default:
					break;
			}

			return false;
		}
	}

	if(formulaType != FORMULA_VALUE)
		return false;

	min = (int32_t)mina;
	max = (int32_t)maxa;
	return true;
}
Example #9
0
bool Combat::getMinMaxValues(Creature* creature, Creature* target, CombatParams& _params, int32_t& min, int32_t& max) const
{
	if(creature)
	{
		if(creature->getCombatValues(min, max))
			return true;

		if(Player* player = creature->getPlayer())
		{
			if(params.valueCallback)
			{
				params.valueCallback->getMinMaxValues(player, _params, min, max);
				return true;
			}

			min = max = 0;
			switch(formulaType)
			{
				case FORMULA_LEVELMAGIC:
				{
					max = (int32_t)((player->getLevel() * 2 + player->getMagicLevel() * 3) * 1. * mina + minb);
					min = (int32_t)((player->getLevel() * 2 + player->getMagicLevel() * 3) * 1. * maxa + maxb);

					player->increaseCombatValues(min, max, params.useCharges, true);
					return true;
				}

				case FORMULA_SKILL:
				{
					Item* item = player->getWeapon(false);
					if(const Weapon* weapon = g_weapons->getWeapon(item))
					{
						_params.element.type = item->getElementType();
						if(_params.element.type != COMBAT_NONE)
						{
							_params.element.damage = weapon->getWeaponElementDamage(player, item, true);
							_params.element.damage = random_range((int32_t)0, (int32_t)(_params.element.damage * maxa + maxb), DISTRO_NORMAL);
						}

						max = (int32_t)(weapon->getWeaponDamage(player, target, item, true) * maxa + maxb);
						if(params.useCharges && item->hasCharges() && g_config.getBool(ConfigManager::REMOVE_WEAPON_CHARGES))
							g_game.transformItem(item, item->getID(), std::max((int32_t)0, ((int32_t)item->getCharges()) - 1));
					}
					else
						max = (int32_t)maxb;

					return true;
				}

				case FORMULA_VALUE:
				{
					min = (int32_t)mina;
					max = (int32_t)maxa;
					return true;
				}

				default:
					min = max = 0;
					break;
			}

			return false;
		}
	}

	if(formulaType != FORMULA_VALUE)
		return false;

	min = (int32_t)mina;
	max = (int32_t)maxa;
	return true;
}