mirror of
https://github.com/ErikasKontenis/SabrehavenServer.git
synced 2025-10-13 14:24:55 +02:00
finish market system
This commit is contained in:
@@ -25,4 +25,5 @@
|
||||
<event class="Player" method="onGainExperience" enabled="1" />
|
||||
<event class="Player" method="onLoseExperience" enabled="0" />
|
||||
<event class="Player" method="onGainSkillTries" enabled="1" />
|
||||
<event class="Player" method="onLookInMarket" enabled="1" />
|
||||
</events>
|
||||
|
@@ -218,6 +218,293 @@ function Player:onLookInTrade(partner, item, distance)
|
||||
self:sendTextMessage(MESSAGE_INFO_DESCR, "You see " .. item:getDescription(distance))
|
||||
end
|
||||
|
||||
|
||||
local showAtkWeaponTypes = {WEAPON_CLUB, WEAPON_SWORD, WEAPON_AXE, WEAPON_DISTANCE}
|
||||
local showDefWeaponTypes = {WEAPON_CLUB, WEAPON_SWORD, WEAPON_AXE, WEAPON_DISTANCE, WEAPON_SHIELD}
|
||||
function Player:onLookInMarket(itemType)
|
||||
local response = NetworkMessage()
|
||||
response:addByte(0xF8)
|
||||
response:addU16(itemType:getId())
|
||||
|
||||
-- armor
|
||||
do
|
||||
local armor = itemType:getArmor()
|
||||
if armor > 0 then
|
||||
response:addString(armor)
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- weapon data (will be reused)
|
||||
local weaponType = itemType:getWeaponType()
|
||||
|
||||
-- attack
|
||||
do
|
||||
local showAtk = table.contains(showAtkWeaponTypes, weaponType)
|
||||
if showAtk then
|
||||
local atkAttrs = {}
|
||||
local atk = itemType:getAttack()
|
||||
if itemType:isBow() then
|
||||
if atk ~= 0 then
|
||||
atkAttrs[#atkAttrs + 1] = string.format("%+d", atk)
|
||||
end
|
||||
|
||||
local hitChance = itemType:getHitChance()
|
||||
if hitChance ~= 0 then
|
||||
atkAttrs[#atkAttrs + 1] = string.format("chance to hit %+d%%", hitChance)
|
||||
end
|
||||
|
||||
atkAttrs[#atkAttrs + 1] = string.format("%d fields", itemType:getShootRange())
|
||||
else
|
||||
atkAttrs[#atkAttrs + 1] = atk
|
||||
local elementDmg = 0
|
||||
if elementDmg ~= 0 then
|
||||
atkAttrs[#atkAttrs] = string.format("%d physical %+d %s", atkAttrs[#atkAttrs], elementDmg, getCombatName(itemType:getElementType()))
|
||||
end
|
||||
end
|
||||
|
||||
response:addString(table.concat(atkAttrs, ", "))
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- container slots
|
||||
do
|
||||
if itemType:isContainer() then
|
||||
response:addString(itemType:getCapacity())
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- defense
|
||||
do
|
||||
local showDef = table.contains(showDefWeaponTypes, weaponType)
|
||||
if showDef then
|
||||
local def = itemType:getDefense()
|
||||
if weaponType == WEAPON_DISTANCE then
|
||||
-- throwables
|
||||
if ammoType ~= AMMO_ARROW and ammoType ~= AMMO_BOLT then
|
||||
response:addString(def)
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
else
|
||||
-- extra def
|
||||
--local xD = itemType:getExtraDefense()
|
||||
--if xD ~= 0 then
|
||||
-- def = string.format("%d %+d", def, xD)
|
||||
--end
|
||||
|
||||
response:addString(def)
|
||||
end
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- description
|
||||
do
|
||||
local desc = itemType:getDescription()
|
||||
if desc and #desc > 0 then
|
||||
response:addString(desc:sub(1, -2))
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- duration
|
||||
do
|
||||
local duration = itemType:getDuration()
|
||||
if duration == 0 then
|
||||
local transferType = itemType:getTransformEquipId()
|
||||
if transferType ~= 0 then
|
||||
transferType = ItemType(transferType)
|
||||
duration = transferType and transferType:getDuration() or duration
|
||||
end
|
||||
end
|
||||
|
||||
if duration > 0 then
|
||||
response:addString(Game.getCountdownString(duration, true, true))
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- item abilities (will be reused)
|
||||
local abilities = itemType:getAbilities()
|
||||
|
||||
-- element protections
|
||||
do
|
||||
local protections = {}
|
||||
for element, value in pairs(abilities.absorbPercent) do
|
||||
if value ~= 0 then
|
||||
protections[#protections + 1] = string.format("%s %+d%%", getCombatName(2 ^ (element - 1)), value)
|
||||
end
|
||||
end
|
||||
|
||||
if #protections > 0 then
|
||||
response:addString(table.concat(protections, ", "))
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- level req
|
||||
do
|
||||
local minLevel = itemType:getMinReqLevel()
|
||||
if minLevel > 0 then
|
||||
response:addString(minLevel)
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- magic level req
|
||||
do
|
||||
local minMagicLevel = itemType:getMinReqMagicLevel()
|
||||
if minMagicLevel > 0 then
|
||||
response:addString(minMagicLevel)
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- vocation
|
||||
do
|
||||
local vocations = itemType:getVocationString()
|
||||
if vocations and vocations:len() > 0 then
|
||||
response:addString(vocations)
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- rune words
|
||||
do
|
||||
local spellName = itemType:getRuneSpellName()
|
||||
if spellName and spellName:len() > 0 then
|
||||
response:addString(spellName)
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- "skill boost" category
|
||||
do
|
||||
-- skill boost
|
||||
local skillBoosts = {}
|
||||
if abilities.manaGain > 0 or abilities.healthGain > 0 or abilities.regeneration then
|
||||
skillBoosts[#skillBoosts + 1] = "faster regeneration"
|
||||
end
|
||||
|
||||
-- invisibility
|
||||
if abilities.invisible then
|
||||
skillBoosts[#skillBoosts + 1] = "invisibility"
|
||||
end
|
||||
|
||||
-- magic shield (classic)
|
||||
if abilities.manaShield then
|
||||
skillBoosts[#skillBoosts + 1] = "magic shield"
|
||||
end
|
||||
|
||||
-- stats (hp/mp/soul/ml)
|
||||
for stat, value in pairs(abilities.stats) do
|
||||
if value ~= 0 then
|
||||
skillBoosts[#skillBoosts + 1] = string.format("%s %+d", getStatName(stat - 1), value)
|
||||
end
|
||||
end
|
||||
|
||||
-- stats but in %
|
||||
for stat, value in pairs(abilities.statsPercent) do
|
||||
if value ~= 0 then
|
||||
skillBoosts[#skillBoosts + 1] = string.format("%s %+d%%", getStatName(stat - 1), value)
|
||||
end
|
||||
end
|
||||
|
||||
-- speed
|
||||
if abilities.speed ~= 0 then
|
||||
skillBoosts[#skillBoosts + 1] = string.format("speed %+d", math.floor(abilities.speed / 2))
|
||||
end
|
||||
|
||||
-- skills
|
||||
for skill, value in pairs(abilities.skills) do
|
||||
if value ~= 0 then
|
||||
skillBoosts[#skillBoosts + 1] = string.format("%s %+d", getSkillName(skill - 1), value)
|
||||
end
|
||||
end
|
||||
|
||||
-- add to response
|
||||
if #skillBoosts > 0 then
|
||||
response:addString(table.concat(skillBoosts, ", "))
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- charges
|
||||
do
|
||||
if itemType:hasShowCharges() then
|
||||
response:addString(itemType:getCharges())
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- weapon type
|
||||
do
|
||||
if itemType:isWeapon() then
|
||||
response:addString(itemType:getWeaponString())
|
||||
else
|
||||
response:addU16(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- weight
|
||||
response:addString(string.format("%0.2f", itemType:getWeight() / 100))
|
||||
|
||||
-- to do
|
||||
response:addU16(0) -- Imbuement Slots
|
||||
response:addU16(0) -- Magic Shield Capacity
|
||||
response:addU16(0) -- Cleave
|
||||
response:addU16(0) -- Damage Reflection
|
||||
response:addU16(0) -- Perfect Shot
|
||||
response:addU16(0) -- Classification
|
||||
response:addU16(0) -- Tier
|
||||
|
||||
-- buy stats
|
||||
do
|
||||
local stats = itemType:getMarketBuyStatistics()
|
||||
if stats then
|
||||
response:addByte(0x01)
|
||||
response:addU32(stats.numTransactions)
|
||||
response:addU64(stats.totalPrice)
|
||||
response:addU64(stats.highestPrice)
|
||||
response:addU64(stats.lowestPrice)
|
||||
else
|
||||
response:addByte(0x00)
|
||||
end
|
||||
end
|
||||
|
||||
-- sell stats
|
||||
do
|
||||
local stats = itemType:getMarketSellStatistics()
|
||||
if stats then
|
||||
response:addByte(0x01)
|
||||
response:addU32(stats.numTransactions)
|
||||
response:addU64(stats.totalPrice)
|
||||
response:addU64(stats.highestPrice)
|
||||
response:addU64(stats.lowestPrice)
|
||||
else
|
||||
response:addByte(0x00)
|
||||
end
|
||||
end
|
||||
|
||||
response:sendToPlayer(self)
|
||||
end
|
||||
|
||||
function Player:onMoveItem(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
|
||||
return true
|
||||
end
|
||||
|
@@ -138,7 +138,8 @@ function onStartup()
|
||||
db.asyncQuery("DELETE FROM `guild_wars` WHERE `status` = 0")
|
||||
db.asyncQuery("DELETE FROM `players` WHERE `deletion` != 0 AND `deletion` < " .. os.time())
|
||||
db.asyncQuery("DELETE FROM `ip_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time())
|
||||
|
||||
db.asyncQuery("DELETE FROM `market_history` WHERE `inserted` <= " .. (os.time() - configManager.getNumber(configKeys.MARKET_OFFER_DURATION)))
|
||||
|
||||
-- Move expired bans to ban history
|
||||
local resultId = db.storeQuery("SELECT * FROM `account_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time())
|
||||
if resultId ~= false then
|
||||
|
@@ -14,3 +14,105 @@ local slotBits = {
|
||||
function ItemType.usesSlot(self, slot)
|
||||
return bit.band(self:getSlotPosition(), slotBits[slot] or 0) ~= 0
|
||||
end
|
||||
|
||||
function ItemType.isHelmet(self)
|
||||
return self:usesSlot(CONST_SLOT_HEAD)
|
||||
end
|
||||
|
||||
function ItemType.isArmor(self)
|
||||
return self:usesSlot(CONST_SLOT_ARMOR)
|
||||
end
|
||||
|
||||
function ItemType.isLegs(self)
|
||||
return self:usesSlot(CONST_SLOT_LEGS)
|
||||
end
|
||||
|
||||
function ItemType.isBoots(self)
|
||||
return self:usesSlot(CONST_SLOT_FEET)
|
||||
end
|
||||
|
||||
local notWeapons = {WEAPON_NONE, WEAPON_SHIELD, WEAPON_AMMO}
|
||||
function ItemType.isWeapon(self)
|
||||
return not table.contains(notWeapons, self:getWeaponType())
|
||||
end
|
||||
|
||||
function ItemType.isTwoHanded(self)
|
||||
return bit.band(self:getSlotPosition(), SLOTP_TWO_HAND) ~= 0
|
||||
end
|
||||
|
||||
function ItemType.isBow(self)
|
||||
local ammoType = self:getAmmoType()
|
||||
return self:getWeaponType() == WEAPON_DISTANCE and (ammoType == AMMO_ARROW or ammoType == AMMO_BOLT)
|
||||
end
|
||||
|
||||
function ItemType.isMissile(self)
|
||||
local ammoType = self:getAmmoType()
|
||||
return self:getWeaponType() == WEAPON_DISTANCE and ammoType ~= AMMO_ARROW and ammoType ~= AMMO_BOLT
|
||||
end
|
||||
|
||||
function ItemType.isWand(self)
|
||||
return self:getWeaponType() == WEAPON_WAND
|
||||
end
|
||||
|
||||
function ItemType.isShield(self)
|
||||
return self:getWeaponType() == WEAPON_SHIELD
|
||||
end
|
||||
|
||||
function ItemType.isBackpack(self)
|
||||
return self:usesSlot(CONST_SLOT_BACKPACK)
|
||||
end
|
||||
|
||||
function ItemType.isNecklace(self)
|
||||
return self:usesSlot(CONST_SLOT_NECKLACE)
|
||||
end
|
||||
|
||||
function ItemType.isRing(self)
|
||||
return self:usesSlot(CONST_SLOT_RING)
|
||||
end
|
||||
|
||||
function ItemType.isAmmo(self)
|
||||
return self:getWeaponType() == WEAPON_AMMO
|
||||
end
|
||||
|
||||
function ItemType.isTrinket(self)
|
||||
return self:usesSlot(CONST_SLOT_AMMO) and self:getWeaponType() == WEAPON_NONE
|
||||
end
|
||||
|
||||
function ItemType.isKey(self)
|
||||
return self:getType() == ITEM_TYPE_KEY
|
||||
end
|
||||
|
||||
function ItemType.isBed(self)
|
||||
return self:getType() == ITEM_TYPE_BED
|
||||
end
|
||||
|
||||
function ItemType.isSplash(self)
|
||||
return self:getGroup() == ITEM_GROUP_SPLASH
|
||||
end
|
||||
|
||||
function ItemType.isPodium(self)
|
||||
return self:getGroup() == ITEM_GROUP_PODIUM
|
||||
end
|
||||
|
||||
function ItemType.getWeaponString(self)
|
||||
local weaponType = self:getWeaponType()
|
||||
local weaponString = "unknown"
|
||||
|
||||
if weaponType == WEAPON_CLUB then
|
||||
weaponString = "blunt instrument"
|
||||
elseif weaponType == WEAPON_SWORD then
|
||||
weaponString = "stabbing weapon"
|
||||
elseif weaponType == WEAPON_AXE then
|
||||
weaponString = "cutting weapon"
|
||||
elseif weaponType == WEAPON_DISTANCE then
|
||||
weaponString = self:isBow() and "firearm" or "missile"
|
||||
elseif weaponType == WEAPON_WAND then
|
||||
weaponString = "wand/rod"
|
||||
end
|
||||
|
||||
if self:isTwoHanded() then
|
||||
weaponString = string.format("%s, two-handed", weaponString)
|
||||
end
|
||||
|
||||
return weaponString
|
||||
end
|
Reference in New Issue
Block a user