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

Added ML Quivers (dfn clothing) #301

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
28 changes: 28 additions & 0 deletions data/dfndata/items/gear/clothing/clothing.dfn
Original file line number Diff line number Diff line change
Expand Up @@ -489,3 +489,31 @@ id=0x1ffe
{
get=0x1ffd 0x1ffe
}

[0x2FB7]
{
get=base_item
name=a quiver
id=0x2FB7
type=1
weight=200
weightmax=50000
maxitems=500
value=400 200
value=2 1
layer=0x14
script=5061
custominttag=WeightReduction 50
}

[0x3171]
{
get=0x2FB7
name=a quiver
id=0x3171
}

[quiver]
{
get=0x3171 0x2FB7
}
39 changes: 36 additions & 3 deletions data/js/item/archerybutte.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
function onUseUnChecked( pUser, iUsed )
{
var pSock = pUser.socket;
var cloakItem = pUser.FindItemLayer( 0x14 );
// Check for ammo type in the quiver
var ammoType = cloakItem.GetTag( "AmmoType" );
var lastUsedBy = iUsed.GetTag( "lastUsedBy" );
var lastUsed = iUsed.GetTag( "lastUsed" );
var timeNow = GetCurrentClock();
Expand Down Expand Up @@ -140,7 +143,19 @@ function onUseUnChecked( pUser, iUsed )
case "BOWS":
var combatAnim = 18;
var arrowCount = pUser.ResourceCount( 0x0F3F, 0 );
if( arrowCount == 0 )
var totalAmmoCount = 0;
for( var mItem = cloakItem.FirstItem(); !cloakItem.FinishedItems(); mItem = cloakItem.NextItem() )
{
if( ammoType == "Arrow" && mItem.id == 0x0f3f )
{
totalAmmoCount += mItem.amount;
if( mItem.amount > 0 )
mItem.amount -= 1;
else
mItem.Delete();
}
}
if( arrowCount == 0 && totalAmmoCount == 0)
{
pUser.SysMessage( GetDictionaryEntry( 1770, pSock.language )); // You do not have any arrows with which to practice.
return false;
Expand All @@ -156,7 +171,19 @@ function onUseUnChecked( pUser, iUsed )
case "XBOWS":
var combatAnim = 19;
var boltCount = pUser.ResourceCount( 0x1BFB, 0 );
if( boltCount == 0 )
var totalAmmoCount = 0;
for( var mItem = cloakItem.FirstItem(); !cloakItem.FinishedItems(); mItem = cloakItem.NextItem() )
{
if( ammoType == "Bolt" && mItem.id == 0x1bfb )
{
totalAmmoCount += mItem.amount;
if( mItem.amount > 0 )
mItem.amount -= 1;
else
mItem.Delete();
}
}
if( boltCount == 0 && totalAmmoCount == 0)
{
pUser.SysMessage( GetDictionaryEntry( 1771, pSock.language )); // You do not have any bolts with which to practice.
return false;
Expand All @@ -168,10 +195,11 @@ function onUseUnChecked( pUser, iUsed )
var stuckBolts = iUsed.GetTag( "stuckBolts" ) + 1;
iUsed.SetTag( "stuckBolts", stuckBolts );
}
break;
}
pUser.DoAction( combatAnim );
ammoType = parseInt( ammoType );
DoMovingEffect( pUser, iUsed, ammoType, 0x06, 0x00, false );
DoMovingEffect( pUser.x, pUser.y, pUser.z + 10, iUsed.x, iUsed.y, iUsed.z + 10, ammoType, 0x06, 0x00, false );
var points = 0;
if( !pUser.CheckSkill( 31, 0, 250 ))
{
Expand Down Expand Up @@ -338,6 +366,11 @@ function onUseUnChecked( pUser, iUsed )
iUsed.SetTag( "lastUsedBy", ( pUser.serial & 0x00FFFFFF ) );
var lastUsed = GetCurrentClock();
iUsed.SetTag( "lastUsed", lastUsed );
if( totalAmmoCount != 0 )
{
cloakItem.SetTag( "AmmoCount", totalAmmoCount - 1 );
cloakItem.Refresh();
}

// Report overall score
var tempMsg = GetDictionaryEntry( 2464, pSock.language ) // Score: %i after %u shots.
Expand Down
52 changes: 52 additions & 0 deletions data/js/item/equip_effects/updatequivercount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
function onSwing(iSwung, pAttacker, pSwingAt)
{
UpdateQuiverCount(pAttacker);
return true;
}

function onAttack( pAttacker, pDefender, hitStatus, hitLoc, damageDealt )
{
UpdateQuiverCount(pAttacker);
return true;
}

function UpdateQuiverCount(pAttacker)
{
// Check if the attacker has a bow or crossbow equipped
var weapon = pAttacker.FindItemLayer(0x2);// Assuming 1 is the layer for weapon (adjust if necessary)
var isBow = weapon.id == 0x13B2 || weapon.id == 0x13B1; // IDs for bows
var isCrossbow = weapon.id == 0x13FD || weapon.id == 0x13FC; // IDs for crossbows

// If neither a bow nor a crossbow is equipped, return early
if (!isBow && !isCrossbow)
{
return true;
}

// Check if there is a quiver (or any item) equipped on the cloak layer (assumed to be layer 14)
var cloakItem = pAttacker.FindItemLayer(0x14);

// If there is no item equipped on the cloak layer, or it's not a container, return early
if (!ValidateObject(cloakItem) || !cloakItem.container)
{
return true;
}

// Check for ammo type in the quiver
var ammoType = cloakItem.GetTag("AmmoType");

var totalAmmoCount = 0;
for (var mItem = cloakItem.FirstItem(); !cloakItem.FinishedItems(); mItem = cloakItem.NextItem()) {
if ((ammoType == "Arrow" && mItem.id == 0x0f3f) || (ammoType == "Bolt" && mItem.id == 0x1bfb)) {
totalAmmoCount += mItem.amount;
}
}
if (totalAmmoCount != 0)
{
cloakItem.SetTag("AmmoCount", totalAmmoCount - 1);
cloakItem.Refresh();
}
return true;
}

function _restorecontext_() {}
147 changes: 147 additions & 0 deletions data/js/item/quivers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
function onEquip(pEquipper, iEquipped)
{
if (!pEquipper.HasScriptTrigger(5062))
{
pEquipper.AddScriptTrigger(5062);
}
return false;
}

function onUnequip(pUnequipper, iUnequipped)
{
pUnequipper.RemoveScriptTrigger(5062);
return false;
}

function onDropItemOnItem(iDropped, cDropper, iDroppedOn)
{
// Prevent the quiver from being dropped onto itself
if (iDropped.id == 0x2FB7 && iDroppedOn.id == 0x2FB7)
{
cDropper.SysMessage("You cannot drop the quiver onto itself.");
return false;
}

// Allow the quiver to be dropped into any container that is not itself
if (iDropped.id == 0x2FB7)
{
return true;
}

// Initialize AmmoCount and WeightReduction tags if they don't exist
if (iDroppedOn.GetTag("AmmoCount") == null)
{
iDroppedOn.SetTag("AmmoCount", 0);
}

if (iDroppedOn.GetTag("WeightReduction") == null)
{
iDroppedOn.SetTag("WeightReduction", 50); // Example: 50% weight reduction
}

// Retrieve the type of ammo currently in the quiver
var ammo = iDroppedOn.GetTag("AmmoType");
var ammoCount = iDroppedOn.GetTag("AmmoCount");
var weightReduction = iDroppedOn.GetTag("WeightReduction");

// Check if adding the dropped ammo would exceed the maximum limit
var maxAmmoCount = 500; // Define maximum ammo count
if (ammoCount + iDropped.amount > maxAmmoCount)
{
cDropper.SysMessage("The quiver cannot hold more than 500 units of ammo.");
return false;
}

// Check if the item being dropped is an arrow
if ((iDropped.id == 0x0f3f || iDropped.sectionID == "0x0f3f") && (ammo == "" || ammo == "Arrow"))
{
iDroppedOn.SetTag("AmmoType", "Arrow");
ammoCount += iDropped.amount; // Add the amount of dropped arrows to the count
iDroppedOn.SetTag("AmmoCount", ammoCount);

// Apply weight reduction
iDropped.weight -= iDropped.weight * (weightReduction / 100);
iDropped.Refresh();
iDroppedOn.Refresh();
return true;
}
// Check if the item being dropped is a bolt
else if ((iDropped.id == 0x1bfb || iDropped.sectionID == "0x1bfb") && (ammo == "" || ammo == "Bolt"))
{
iDroppedOn.SetTag("AmmoType", "Bolt");
ammoCount += iDropped.amount; // Add the amount of dropped bolts to the count
iDroppedOn.SetTag("AmmoCount", ammoCount);

// Apply weight reduction
iDropped.weight -= iDropped.weight * (weightReduction / 100);
iDropped.Refresh();
iDroppedOn.Refresh();
return true;
}
// If the ammo type doesn't match or the quiver already holds a different type of ammo
else
{
cDropper.SysMessage("The container cannot hold that type of object.");
return false;
}
}

function onContRemoveItem(iCont, iItem, pChar)
{
// Validate the container and item objects
if (!ValidateObject(iCont) || !ValidateObject(iItem))
return;

// Check if the container is a quiver (id 0x2FB7)
if (iCont.id == 0x2FB7)
{
var ammoType = iCont.GetTag("AmmoType");
var ammoCount = iCont.GetTag("AmmoCount");
var weightReduction = iCont.GetTag("WeightReduction");

// Check if the item being removed matches the ammo type
if ((ammoType == "Arrow" && iItem.id == 0x0f3f) || (ammoType == "Bolt" && iItem.id == 0x1bfb))
{
// Restore the original weight
iItem.weight += iItem.weight * (weightReduction / (100 - weightReduction));
iItem.Refresh();

// Decrease the ammo count by the amount being removed
ammoCount -= iItem.amount;

// Update the AmmoCount tag
iCont.SetTag("AmmoCount", ammoCount);

// If ammo count is zero or less, reset the AmmoType and AmmoCount tags
if (ammoCount <= 0)
{
iCont.SetTag("AmmoType", "");
iCont.SetTag("AmmoCount", 0);
pChar.SysMessage("The quiver is now empty and can hold a different type of ammo.");
}
}
}
}

function onTooltip(equipment, pSocket)
{
var weightReduction = parseInt(equipment.GetTag("WeightReduction")); // Default to 0 if not set
var ammoCount = equipment.GetTag("AmmoCount"); // Default to 0 if not set
var ammoType = equipment.GetTag("AmmoType");
var tooltipText = "";

// Add weight reduction information
tooltipText = "Weight reduction: " + weightReduction + "%";

// Add ammo information
if (ammoType != null && ammoType != "")
{
tooltipText += "\n" + "Ammo: " + ammoCount + "/500 " + ammoType + "s";
}
else
{
tooltipText += "\n" + "Ammo: " + ammoCount + "/500";
}

return tooltipText;
}
2 changes: 2 additions & 0 deletions data/js/jse_fileassociations.scp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@
5058=item/bagofsending.js
5059=item/powderoftranslocation.js
5060=item/elixirofingots.js
5061=item/quivers.js
5062=item/equip_effects/updatequivercount.js

//-------------------------------------------
// treasure maps and chest [5400-5405]
Expand Down
3 changes: 3 additions & 0 deletions source/Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
14/08/2024 - Dragon Slayer/Xuri
Added ML Quivers (dfn clothing)

1/05/2024 - Dragon Slayer/Xuri
Fixed AutoUnequipAttempt function in clumsy.js, createfood.js level1target.js, will no longer fail on casting and return to hardcode.
Fixed createfood to check for reagents on cast.
Expand Down
2 changes: 1 addition & 1 deletion source/combat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2806,7 +2806,7 @@ bool CHandleCombat::HandleCombat( CSocket *mSock, CChar& mChar, CChar *ourTarg )
UI16 ammoFXHue = mWeapon->GetAmmoFXHue();
UI16 ammoFXRender = mWeapon->GetAmmoFXRender();

if( mChar.IsNpc() || ( ammoId != 0 && DeleteItemAmount( &mChar, 1, ammoId, ammoHue ) == 1 ))
if( mChar.IsNpc() || ( ammoId != 0 && DeleteQuiverItemAmount( &mChar, 1, ammoId, ammoHue ) == 1 ))
{
PlaySwingAnimations( &mChar );
//Effects->PlayMovingAnimation( &mChar, ourTarg, ammoFX, 0x08, 0x00, 0x00, static_cast<UI32>( ammoFXHue ), static_cast<UI32>( ammoFXRender ));
Expand Down
1 change: 1 addition & 0 deletions source/funcdecl.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ UI32 DeleteItemAmount( CChar *s, UI32 amount, UI16 realId, UI16 realColour = 0x0
UI32 DeleteSubItemAmount( CItem *p, UI32 amount, UI16 realId, UI16 realColour = 0x0000, UI32 realMoreVal = 0x0, bool colorCheck = false, bool moreCheck = false, std::string sectionId = "" );
UI32 GetBankCount( CChar *p, UI16 itemId, UI16 realColour = 0x0000, UI32 realMoreVal = 0x0 );
UI32 DeleteBankItem( CChar *p, UI32 amt, UI16 itemId, UI16 realColour = 0x0000, UI32 realMoreVal = 0x0 );
UI32 DeleteQuiverItemAmount( CChar *s, UI32 amount, UI16 realId, UI16 realColour = 0x0000, UI32 realMoreVal = 0x0, bool colorCheck = false, bool moreCheck = false, std::string sectionId = "" );

//o------------------------------------------------------------------------------------------------o
// Region related
Expand Down
2 changes: 2 additions & 0 deletions source/items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,8 @@ PackTypes cItem::GetPackType( CItem *i )
break;
case 0x24DB: // SE basket
case 0x24DC: // SE basket
case 0x2FB7: // ML quiver
case 0x3171: // ML quiver
packType = PT_SEBASKET;
break;
case 0x280B: // SE chest
Expand Down
33 changes: 33 additions & 0 deletions source/quantityfuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,36 @@ UI32 DeleteBankItem( CChar *p, UI32 amt, UI16 itemId, UI16 colour, UI32 moreVal
return amt;
}

//o------------------------------------------------------------------------------------------------o
//| Function - DeleteQuiverItemAmount()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Remove a certain amount of an item of specified color from quiver equipped on a character
//| If it fails to remove the full amount from quiver, try from regular backpack as well
//o------------------------------------------------------------------------------------------------o
UI32 DeleteQuiverItemAmount( CChar *s, UI32 amount, UI16 realId, UI16 realColour, UI32 realMoreVal, bool colorCheck, bool moreCheck, std::string sectionId )
{
if( !ValidateObject( s ))
return 0;

UI32 amountDeleted = 0;

// First try to remove from quiver, if it exists in cloak slot
CItem *quiverPack = s->GetItemAtLayer( IL_CLOAK );
if( ValidateObject( quiverPack ) && quiverPack->GetType() == IT_CONTAINER )
{
amountDeleted = DeleteSubItemAmount( quiverPack, amount, realId, realColour, realMoreVal, colorCheck, moreCheck, sectionId );
}

// Then fallback to regular backpack if full amount has not been removed from quiver/quiver didn't exist
if( amountDeleted < amount )
{
CItem *p = s->GetPackItem();
if( !ValidateObject( p ))
return amountDeleted;

amountDeleted += DeleteSubItemAmount( p, amount - amountDeleted, realId, realColour, realMoreVal, colorCheck, moreCheck, sectionId );
}

return amountDeleted;
}

Loading