Skip to content

Commit

Permalink
Merge pull request #6793 from WinterSolstice8/implement_bounty_shot
Browse files Browse the repository at this point in the history
Implement bounty shot
  • Loading branch information
zach2good authored Jan 23, 2025
2 parents 4d0b61c + 33ac36f commit 420276f
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 6 deletions.
2 changes: 1 addition & 1 deletion scripts/actions/abilities/bounty_shot.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ abilityObject.onAbilityCheck = function(player, target, ability)
end

abilityObject.onUseAbility = function(player, target, ability, action)
-- target:addStatusEffect(xi.effect.BOUNTY_SHOT, 11, 1, 30) -- TODO: implement xi.effect.BOUNTY_SHOT
return xi.job_utils.ranger.useBountyShot(player, target, ability, action)
end

return abilityObject
3 changes: 3 additions & 0 deletions scripts/enum/mod.lua
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,9 @@ xi.mod =
REPRISAL_SPIKES_BONUS = 1068, -- Increases Reprisal spikes damage by percentage (e.g. mod value of 50 will increase spikes damage by 50%)
SHIELD_BARRIER = 1082, -- Grants a bonus to Protect spells cast by self while a shield is equipped.

-- Ranger
BOUNTY_SHOT_TH_BONUS = 826, -- Boosts base TH level of bounty shot

-- Dark Knight
ARCANE_CIRCLE_DURATION = 858, -- Arcane Circle extended duration in seconds
ARCANE_CIRCLE_POTENCY = 1069, -- Increases the potency of the Arcane Circle effect (e.g. mod value 2 = +2% Arcana Killer)
Expand Down
1 change: 1 addition & 0 deletions scripts/enum/msg.lua
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ xi.msg.basic =
STATUS_BOOST_2 = 365, -- All of <target>'s status parameters are boosted.
JA_MAGIC_BURST = 379, -- <user> uses <ability>. Magic Burst! the <target> takes <amount> damage.
JA_ENMITY_DECREASE = 743, -- <user> uses <ability>. <target>'s enmity decreases.
JA_TH_EFFECTIVENESS = 608, -- <user> uses <ability>. Treasure Hunter effectiveness against <target> increases to <amount>.

-- "Fortified against" messages
FORTIFIED_DEMONS = 149, -- <target> is fortified against demons.
Expand Down
76 changes: 74 additions & 2 deletions scripts/globals/job_utils/ranger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,20 @@ xi.job_utils.ranger.checkDoubleShot = function(player, target, ability)
end

xi.job_utils.ranger.checkBountyShot = function(player, target, ability)
return 0, 0
if target:getObjType() ~= xi.objType.MOB then
return xi.msg.basic.CANNOT_ATTACK_TARGET, 0
end

if
(player:getWeaponSkillType(xi.slot.RANGED) == xi.skill.MARKSMANSHIP and
player:getWeaponSkillType(xi.slot.AMMO) == xi.skill.MARKSMANSHIP) or
(player:getWeaponSkillType(xi.slot.RANGED) == xi.skill.ARCHERY and
player:getWeaponSkillType(xi.slot.AMMO) == xi.skill.ARCHERY)
then
return 0, 0
end

return xi.msg.basic.NO_RANGED_WEAPON, 0
end

xi.job_utils.ranger.checkDecoyShot = function(player, target, ability)
Expand Down Expand Up @@ -261,7 +274,66 @@ xi.job_utils.ranger.useDoubleShot = function(player, target, ability, action)
end

xi.job_utils.ranger.useBountyShot = function(player, target, ability, action)
return 0, 0 -- Not implemented yet
local mobTHLevel = target:getTHlevel()
local bountyShotTHLevel = 2 + player:getMod(xi.mod.BOUNTY_SHOT_TH_BONUS)
local playerTHLevel = player:getMod(xi.mod.TREASURE_HUNTER)
local newTHLevel = 0

player:removeAmmo()
action:speceffect(target:getID(), 0x01) -- functional, animation not correct without this
ability:setMsg(xi.msg.basic.JA_NO_EFFECT_2)

target:updateClaim(player)

-- pre-apply up to max value of TH4
if mobTHLevel < 4 and playerTHLevel > mobTHLevel then
newTHLevel = math.min(4, playerTHLevel)

target:setTHlevel(newTHLevel)

mobTHLevel = newTHLevel
end

-- 100% success rate if bounty shot level is higher than their TH level
if bountyShotTHLevel > mobTHLevel then
ability:setMsg(xi.msg.basic.JA_TH_EFFECTIVENESS)
target:setTHlevel(bountyShotTHLevel)

return bountyShotTHLevel
end

-- https://www.bg-wiki.com/ffxi/Bounty_Shot
-- https://wiki.ffo.jp/html/22203.html
if mobTHLevel < 12 + player:getMod(xi.mod.TREASURE_HUNTER_CAP) then
local treausureHunterLevelDiff = mobTHLevel - bountyShotTHLevel

-- TODO: this rate is the same as THF treasure hunter procs. It is unclear if this has the same rate or better than THF auto attacks.
-- This also assumes proc rate bonus works on Bounty Shot, but without mountains of data I wouldn't be able to tell.
-- JP wiki implies these rates and functionality is the same as THF, but there's no data.
-- BG wiki claims proc rates are similar to SA + TA procs, which seems likely given the 1 min timer on bounty shot.
local procRate = 0.10 / math.pow(2, treausureHunterLevelDiff)
local procRateBonus = 1.0 + (target:getMod(xi.mod.TREASURE_HUNTER_PROC) + player:getMod(xi.mod.TREASURE_HUNTER_PROC)) / 100

if math.random() < procRate * procRateBonus then
newTHLevel = mobTHLevel + 1

ability:setMsg(xi.msg.basic.JA_TH_EFFECTIVENESS)

target:setTHlevel(newTHLevel)

return newTHLevel
end
end

-- If we got here, TH was upgraded to 3 or 4 from gear
-- JP wiki indicates this doesn't happen, but printing incorrectly that the action didn't boost TH level seems weird
if newTHLevel > 0 then
ability:setMsg(xi.msg.basic.JA_TH_EFFECTIVENESS)

return newTHLevel
end

return 0
end

xi.job_utils.ranger.useDecoyShot = function(player, target, ability, action)
Expand Down
6 changes: 6 additions & 0 deletions scripts/specs/core/CBaseEntity.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3938,6 +3938,12 @@ end
function CBaseEntity:getTHlevel()
end

---@nodiscard
---@param newLevel integer
---@return nil
function CBaseEntity:setTHlevel(newLevel)
end

---@nodiscard
---@return integer
function CBaseEntity:getAvailableTraverserStones()
Expand Down
2 changes: 1 addition & 1 deletion sql/abilities.sql
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ INSERT INTO `abilities` VALUES (280,'scarlet_delirium',8,95,1,90,44,100,0,250,20
-- INSERT INTO `abilities` VALUES (282,'run_wild',9,93,1,900,46,100,0,255,2000,0,6,20.0,0,0,0,0,0,NULL); -- needs animation
INSERT INTO `abilities` VALUES (283,'tenuto',10,83,1,5,47,0,0,257,2000,0,6,20.0,0,0,0,0,0,'ABYSSEA');
INSERT INTO `abilities` VALUES (284,'marcato',10,95,1,600,48,0,0,251,2000,0,6,20.0,0,0,0,0,0,'ABYSSEA');
INSERT INTO `abilities` VALUES (285,'bounty_shot',11,87,4,60,51,100,0,261,2000,0,6,20.0,0,0,0,0,0,NULL);
INSERT INTO `abilities` VALUES (285,'bounty_shot',11,87,4,60,51,100,0,189,2000,0,3,21.0,0,0,0,0,0,NULL);
INSERT INTO `abilities` VALUES (286,'decoy_shot',11,95,4,300,52,100,0,261,2000,0,6,20.0,0,0,0,0,0,NULL); -- needs animation
INSERT INTO `abilities` VALUES (287,'hamanoha',12,87,4,300,53,100,0,249,2000,0,6,12.0,0,0,0,0,0,NULL);
INSERT INTO `abilities` VALUES (288,'hagakure',12,95,1,180,54,0,0,249,2000,0,6,20.0,0,1,80,0,0,'ABYSSEA');
Expand Down
6 changes: 5 additions & 1 deletion sql/item_mods.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5026,6 +5026,7 @@ INSERT INTO `item_mods` VALUES (11114,1,25); -- DEF: 25
INSERT INTO `item_mods` VALUES (11114,8,10); -- STR: 10
INSERT INTO `item_mods` VALUES (11114,73,7); -- STORETP: 7
INSERT INTO `item_mods` VALUES (11114,104,7); -- ARCHERY: 7
INSERT INTO `item_mods` VALUES (11114,826,1); -- BOUNTY_SHOT_TH_BONUS: 1

-- Unkai Kote +2
INSERT INTO `item_mods` VALUES (11115,1,31); -- DEF: 31
Expand Down Expand Up @@ -5719,6 +5720,7 @@ INSERT INTO `item_mods` VALUES (11214,1,23); -- DEF: 23
INSERT INTO `item_mods` VALUES (11214,8,7); -- STR: 7
INSERT INTO `item_mods` VALUES (11214,73,4); -- STORETP: 4
INSERT INTO `item_mods` VALUES (11214,104,5); -- ARCHERY: 5
INSERT INTO `item_mods` VALUES (11214,826,1); -- BOUNTY_SHOT_TH_BONUS: 1

-- Unkai Kote +1
INSERT INTO `item_mods` VALUES (11215,1,29); -- DEF: 29
Expand Down Expand Up @@ -50761,7 +50763,7 @@ INSERT INTO `item_mods` VALUES (23229,73,10); -- STORETP: 10
INSERT INTO `item_mods` VALUES (23229,104,33); -- ARCHERY: 33
INSERT INTO `item_mods` VALUES (23229,160,-1000); -- DMG: -10%
INSERT INTO `item_mods` VALUES (23229,384,500); -- HASTE_GEAR: 5%
-- TODO: "Bounty Shot"+3
INSERT INTO `item_mods` VALUES (23229,826,3); -- BOUNTY_SHOT_TH_BONUS: 3

-- Kasuga Kote +2
INSERT INTO `item_mods` VALUES (23230,1,124); -- DEF: 124
Expand Down Expand Up @@ -67829,6 +67831,7 @@ INSERT INTO `item_mods` VALUES (27072,68,12); -- EVA: 12
INSERT INTO `item_mods` VALUES (27072,73,8); -- STORETP: 8
INSERT INTO `item_mods` VALUES (27072,104,18); -- ARCHERY: 18
INSERT INTO `item_mods` VALUES (27072,384,400); -- HASTE_GEAR: 400
INSERT INTO `item_mods` VALUES (27072,826,1); -- BOUNTY_SHOT_TH_BONUS: 1

-- Amini Glovelettes +1
INSERT INTO `item_mods` VALUES (27073,1,88); -- DEF: 88
Expand All @@ -67846,6 +67849,7 @@ INSERT INTO `item_mods` VALUES (27073,68,27); -- EVA: 27
INSERT INTO `item_mods` VALUES (27073,73,9); -- STORETP: 9
INSERT INTO `item_mods` VALUES (27073,104,28); -- ARCHERY: 28
INSERT INTO `item_mods` VALUES (27073,384,500); -- HASTE_GEAR: 500
INSERT INTO `item_mods` VALUES (27073,826,2); -- BOUNTY_SHOT_TH_BONUS: 2

-- Kasuga Kote
INSERT INTO `item_mods` VALUES (27074,1,77); -- DEF: 77
Expand Down
16 changes: 16 additions & 0 deletions src/map/lua/lua_baseentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18040,6 +18040,21 @@ int16 CLuaBaseEntity::getTHlevel()
return 0;
}

/************************************************************************
* Function: setTHlevel()
* Purpose : set mob's Treasure Hunter tier
* Example : target:setTHlevel(5)
************************************************************************/

void CLuaBaseEntity::setTHlevel(int16 newLevel)
{
if (m_PBaseEntity->objtype == TYPE_MOB)
{
CMobEntity* PMob = static_cast<CMobEntity*>(m_PBaseEntity);
PMob->m_THLvl = newLevel;
}
}

/************************************************************************
* Function: getAvailableTraverserStones()
* Purpose : Returns the number of Traverser Stones available for claim
Expand Down Expand Up @@ -19427,6 +19442,7 @@ void CLuaBaseEntity::Register()
SOL_REGISTER("getDespoilDebuff", CLuaBaseEntity::getDespoilDebuff);
SOL_REGISTER("itemStolen", CLuaBaseEntity::itemStolen);
SOL_REGISTER("getTHlevel", CLuaBaseEntity::getTHlevel);
SOL_REGISTER("setTHlevel", CLuaBaseEntity::setTHlevel);

SOL_REGISTER("getPlayerTriggerAreaInZone", CLuaBaseEntity::getPlayerTriggerAreaInZone);
SOL_REGISTER("updateToEntireZone", CLuaBaseEntity::updateToEntireZone);
Expand Down
1 change: 1 addition & 0 deletions src/map/lua/lua_baseentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,7 @@ class CLuaBaseEntity
uint16 getDespoilDebuff(uint16 itemID); // gets the status effect id to apply to the mob on successful despoil
bool itemStolen(); // sets mob's ItemStolen var = true
int16 getTHlevel(); // Returns the Monster's current Treasure Hunter Tier
void setTHlevel(int16 newLevel); // Sets the Monster's current Treasure Hunter Tier

uint32 getAvailableTraverserStones();
time_t getTraverserEpoch();
Expand Down
2 changes: 1 addition & 1 deletion src/map/modifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ enum class Mod
SHARPSHOT = 314, //
TRUE_SHOT_EFFECT = 1053, // TODO: True Shot Ranged Damage increase (percent)
DEAD_AIM_EFFECT = 1054, // TODO: Dead Aim Critical Damage increase (percent)
BOUNTY_SHOT_TH_BONUS = 826, // Boosts base TH level of bounty shot

// Samurai
WARDING_CIRCLE_DURATION = 95, // Warding Circle extended duration in seconds
Expand Down Expand Up @@ -1072,7 +1073,6 @@ enum class Mod
// The spares take care of finding the next ID to use so long as we don't forget to list IDs that have been freed up by refactoring.
// 570 through 825 used by WS DMG mods these are not spares.
//
// SPARE ID: 826
// SPARE IDs: 1132 and onward
};

Expand Down

0 comments on commit 420276f

Please sign in to comment.