SoulfateOriginal

AmmoLimiter.reds

Jul 23rd, 2025
324
0
16 hours
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 30.15 KB | Source Code | 0 0
  1. import Codeware.Localization.*
  2.  
  3. // ### SYSTÈME DE CACHE ###
  4. public abstract class ALDataCache{
  5.     public static func GetCachedALData(ammoType:String,config:ref<AmmoLimiterConfig>) -> ref<ALData>{
  6.         let cache=ALDataCache.EnsureCache();
  7.         let configHash=ALDataCache.GetConfigHash(config);
  8.         let key:Uint64=TDBID.ToNumber(TDBID.Create(ammoType+"_"+configHash));
  9.         if cache.KeyExist(key){return cache.Get(key) as ALData;}
  10.         let data=ALUtils.GetALData(ammoType,config);
  11.         cache.Insert(key,data);
  12.         return data;
  13.     }
  14.  
  15.     private static func GetConfigHash(config:ref<AmmoLimiterConfig>) -> String{
  16.         let hash:String="";
  17.         hash+=ToString(config.handModeSelected);
  18.         hash+="_"+IntToString(config.ammoLimitHandgun);
  19.         hash+="_"+IntToString(config.ammoLimitRifle);
  20.         hash+="_"+IntToString(config.ammoLimitShotgun);
  21.         hash+="_"+IntToString(config.ammoLimitSniper);
  22.         hash+="_"+IntToString(config.ammoBoxHandgun);
  23.         hash+="_"+IntToString(config.ammoBoxRifle);
  24.         hash+="_"+IntToString(config.ammoBoxShotgun);
  25.         hash+="_"+IntToString(config.ammoBoxSniper);
  26.         hash+="_"+FloatToString(config.ammoWeightHandgun);
  27.         hash+="_"+FloatToString(config.ammoWeightRifle);
  28.         hash+="_"+FloatToString(config.ammoWeightShotgun);
  29.         hash+="_"+FloatToString(config.ammoWeightSniper);
  30.         hash+="_"+FloatToString(config.ammoPriceHandgun);
  31.         hash+="_"+FloatToString(config.ammoPriceRifle);
  32.         hash+="_"+FloatToString(config.ammoPriceShotgun);
  33.         hash+="_"+FloatToString(config.ammoPriceSniper);
  34.         return hash;
  35.     }
  36.  
  37.     private static func EnsureCache() -> ref<inkHashMap>{
  38.         let gameInstance=GetGameInstance();
  39.         let system=gameInstance.GetScriptableSystemsContainer().Get(n"ALSystem") as ALSystem;
  40.         return system.GetCache();
  41.     }
  42. }
  43.  
  44.  
  45. // ### UTILITAIRES ###
  46. public class ALData extends IScriptable{
  47.     public let ammoTDBID:TweakDBID;
  48.     public let limit:Int32;
  49.     public let ammoBox:Int32;
  50.     public let handLimit:Int32;
  51.     public let handMin:Int32;
  52.     public let handMax:Int32;
  53.     public let ammoWeight:Float;
  54.     public let priceMult:Float;
  55.     public let ammoConv:Float;
  56.     public let ammoCraft:Int32;
  57. }
  58.  
  59. public class ALUtils{
  60.     public static func GetAmmoTypeNames() -> array<String>{return ["Handgun","Rifle","Shotgun","SniperRifle"];}
  61.  
  62.     public static func GetAmmoTDBID(ammoType:String) -> TweakDBID{return TDBID.Create("Ammo."+ammoType+"Ammo");}
  63.  
  64.     public static func GetAmmoTypeFromID(ammoType:ItemID) -> String{
  65.         let fullName=TDBID.ToStringDEBUG(ItemID.GetTDBID(ammoType));
  66.         return !StrBeginsWith(fullName,"Ammo.")?"":StrEndsWith(fullName,"Ammo") && StrLen(fullName)>9?StrMid(fullName,5,StrLen(fullName)-9):StrMid(fullName,5);
  67.     }
  68.  
  69.     public static func GetAmmoTypeFromWeaponType(weaponType:gamedataItemType) -> String{
  70.         switch weaponType{
  71.             case gamedataItemType.Wea_Handgun:
  72.             case gamedataItemType.Wea_Revolver:
  73.             case gamedataItemType.Wea_SubmachineGun:
  74.                 return "Handgun";
  75.             case gamedataItemType.Wea_AssaultRifle:
  76.             case gamedataItemType.Wea_Rifle:
  77.             case gamedataItemType.Wea_LightMachineGun:
  78.             case gamedataItemType.Wea_HeavyMachineGun:
  79.                 return "Rifle";
  80.             case gamedataItemType.Wea_Shotgun:
  81.             case gamedataItemType.Wea_ShotgunDual:
  82.                 return "Shotgun";
  83.             case gamedataItemType.Wea_SniperRifle:
  84.             case gamedataItemType.Wea_PrecisionRifle:
  85.                 return "SniperRifle";
  86.             default:
  87.                 return "";
  88.         }
  89.     }
  90.  
  91.     public static func GetActiveWeaponAmmoType(player:ref<PlayerPuppet>) -> String{
  92.         let weapon=GameInstance.GetTransactionSystem(player.GetGame()).GetItemInSlot(player,t"AttachmentSlots.WeaponRight") as WeaponObject;
  93.         return IsDefined(weapon)?ALUtils.GetAmmoTypeFromID(WeaponObject.GetAmmoType(weapon)):"";
  94.     }
  95.  
  96.     public static func GetALData(ammoType:String,config:ref<AmmoLimiterConfig>) -> ref<ALData>{
  97.         let data=new ALData();
  98.         data.ammoTDBID=ALUtils.GetAmmoTDBID(ammoType);
  99.         switch ammoType{
  100.             case "Handgun":
  101.                 data.limit=config.ammoLimitHandgun;
  102.                 data.ammoBox=config.ammoBoxHandgun;
  103.                 data.handLimit=config.handLimitHandgun;
  104.                 data.handMin=config.handMinHandgun;
  105.                 data.handMax=config.handMaxHandgun;
  106.                 data.ammoWeight=config.ammoWeightHandgun;
  107.                 data.priceMult=config.ammoPriceHandgun;
  108.                 data.ammoConv=Cast<Float>(config.craftingCompForAmmo)/Cast<Float>(config.ammoCraftHandgun)*Cast<Float>(config.ammoConversionRate);
  109.                 data.ammoCraft=config.ammoCraftHandgun;
  110.                 break;
  111.             case "Rifle":
  112.                 data.limit=config.ammoLimitRifle;
  113.                 data.ammoBox=config.ammoBoxRifle;
  114.                 data.handLimit=config.handLimitRifle;
  115.                 data.handMin=config.handMinRifle;
  116.                 data.handMax=config.handMaxRifle;
  117.                 data.ammoWeight=config.ammoWeightRifle;
  118.                 data.priceMult=config.ammoPriceRifle;
  119.                 data.ammoConv=Cast<Float>(config.craftingCompForAmmo)/Cast<Float>(config.ammoCraftRifle)*Cast<Float>(config.ammoConversionRate);
  120.                 data.ammoCraft=config.ammoCraftRifle;
  121.                 break;
  122.             case "Shotgun":
  123.                 data.limit=config.ammoLimitShotgun;
  124.                 data.ammoBox=config.ammoBoxShotgun;
  125.                 data.handLimit=config.handLimitShotgun;
  126.                 data.handMin=config.handMinShotgun;
  127.                 data.handMax=config.handMaxShotgun;
  128.                 data.ammoWeight=config.ammoWeightShotgun;
  129.                 data.priceMult=config.ammoPriceShotgun;
  130.                 data.ammoConv=Cast<Float>(config.craftingCompForAmmo)/Cast<Float>(config.ammoCraftShotgun)*Cast<Float>(config.ammoConversionRate);
  131.                 data.ammoCraft=config.ammoCraftShotgun;
  132.                 break;
  133.             case "SniperRifle":
  134.                 data.limit=config.ammoLimitSniper;
  135.                 data.ammoBox=config.ammoBoxSniper;
  136.                 data.handLimit=config.handLimitSniper;
  137.                 data.handMin=config.handMinSniper;
  138.                 data.handMax=config.handMaxSniper;
  139.                 data.ammoWeight=config.ammoWeightSniper;
  140.                 data.priceMult=config.ammoPriceSniper;
  141.                 data.ammoConv=Cast<Float>(config.craftingCompForAmmo)/Cast<Float>(config.ammoCraftSniper)*Cast<Float>(config.ammoConversionRate);
  142.                 data.ammoCraft=config.ammoCraftSniper;
  143.                 break;
  144.         }
  145.         return data;
  146.     }
  147. }
  148.  
  149. // ### SYSTÈME DE MESSAGE ###
  150. @addMethod(PlayerPuppet)
  151. private func ALMessage(message:String) -> Void{
  152.     let blackboard=GameInstance.GetBlackboardSystem(this.GetGame()).Get(GetAllBlackboardDefs().UI_Notifications);
  153.     if IsDefined(blackboard){
  154.         let msg:SimpleScreenMessage;
  155.         msg.isShown=true;
  156.         msg.message=message;
  157.         blackboard.SetVariant(GetAllBlackboardDefs().UI_Notifications.OnscreenMessage,ToVariant(msg),true);
  158.     }
  159. }
  160.  
  161. // ### SYSTÈME D’INITIALISATION ###
  162. public class ALDelayCallback extends DelayCallback{
  163.     let m_system:wref<ALSystem>;
  164.  
  165.     public static func Create(system:ref<ALSystem>) -> ref<ALDelayCallback>{
  166.         let callback=new ALDelayCallback();
  167.         callback.m_system=system;
  168.         return callback;
  169.     }
  170.  
  171.     public func Call() -> Void{if IsDefined(this.m_system){this.m_system.ApplyAmmoConfig();}}
  172. }
  173.  
  174. public class ALSystem extends ScriptableSystem{
  175.     private let config:ref<AmmoLimiterConfig>;
  176.     private let m_cache:ref<inkHashMap>;
  177.  
  178.     public static func GetConfig() -> ref<AmmoLimiterConfig>{
  179.         let gameInstance=GetGameInstance();
  180.         let alSystem=gameInstance.GetScriptableSystemsContainer().Get(n"ALSystem") as ALSystem;
  181.         if !IsDefined(alSystem.config){
  182.             alSystem.config=new AmmoLimiterConfig();
  183.         }
  184.         return alSystem.config;
  185.     }
  186.  
  187.     private func OnAttach(){
  188.         this.m_cache=new inkHashMap();
  189.         this.config=new AmmoLimiterConfig();
  190.         this.ApplyAmmoConfig();
  191.         GameInstance.GetCallbackSystem().RegisterCallback(n"Session/Start",this,n"OnSessionStart");
  192.     }
  193.  
  194.     public func GetCache() -> ref<inkHashMap>{return this.m_cache;}
  195.  
  196.     public final func OnSessionStart(evt:ref<GameSessionEvent>) -> Void{GameInstance.GetDelaySystem(this.GetGameInstance()).DelayCallback(ALDelayCallback.Create(this),0.075);}
  197.  
  198.     public final func ApplyAmmoConfig() -> Void{
  199.         this.config=ALSystem.GetConfig();
  200.         let ammoTypes=ALUtils.GetAmmoTypeNames();
  201.         this.CreateAndApplyAmmoMods(this.config,ammoTypes);
  202.         this.ApplyHandSys(this.config,ammoTypes);
  203.         this.ApplyAmmoBoxQties(this.config);
  204.     }
  205.  
  206.     private final func CreateAndApplyAmmoMods(config:ref<AmmoLimiterConfig>,ammoTypes:array<String>) -> Void{
  207.         for ammoType in ammoTypes{
  208.             let ammoData=ALDataCache.GetCachedALData(ammoType,config);
  209.             let basePath="AmmoLimiter."+ammoType;
  210.             let buyModID=TDBID.Create(basePath+".buyPrice");
  211.             let sellModID=TDBID.Create(basePath+".sellPrice");
  212.             let weightModID=TDBID.Create(basePath+".statModifiers");
  213.             let quantityModID=TDBID.Create(basePath+".quantity");
  214.             TweakDBManager.CreateRecord(StringToName(basePath),n"gamedataItem_Record");
  215.             TweakDBManager.CreateRecord(StringToName(basePath+".buyPrice"),n"gamedataConstantStatModifier_Record");
  216.             TweakDBManager.CreateRecord(StringToName(basePath+".sellPrice"),n"gamedataConstantStatModifier_Record");
  217.             TweakDBManager.CreateRecord(StringToName(basePath+".statModifiers"),n"gamedataConstantStatModifier_Record");
  218.             TweakDBManager.CreateRecord(StringToName(basePath+".quantity"),n"gamedataConstantStatModifier_Record");
  219.             TweakDBManager.SetFlat(quantityModID+t".modifierType",n"Additive");
  220.             TweakDBManager.SetFlat(quantityModID+t".statType",t"BaseStats.Quantity");
  221.             TweakDBManager.SetFlat(quantityModID+t".value",9999.0);
  222.             TweakDBManager.SetFlat(buyModID+t".modifierType",n"Multiplier");
  223.             TweakDBManager.SetFlat(buyModID+t".statType",t"BaseStats.Price");
  224.             TweakDBManager.SetFlat(buyModID+t".value",ammoData.priceMult);
  225.             TweakDBManager.SetFlat(sellModID+t".modifierType",n"Multiplier");
  226.             TweakDBManager.SetFlat(sellModID+t".statType",t"BaseStats.Price");
  227.             TweakDBManager.SetFlat(sellModID+t".value",ammoData.priceMult/3.0);
  228.             TweakDBManager.SetFlat(weightModID+t".modifierType",n"Additive");
  229.             TweakDBManager.SetFlat(weightModID+t".statType",t"BaseStats.Weight");
  230.             TweakDBManager.SetFlat(weightModID+t".value",ammoData.ammoWeight);
  231.             TweakDBManager.SetFlat(ammoData.ammoTDBID+t".buyPrice",[t"Price.Ammo",t"Price.BuyPrice_StreetCred_Discount",buyModID]);
  232.             TweakDBManager.SetFlat(ammoData.ammoTDBID+t".sellPrice",[t"Price.Ammo",sellModID]);
  233.             TweakDBManager.SetFlat(ammoData.ammoTDBID+t".statModifiers",[quantityModID,weightModID]);
  234.             TweakDBManager.SetFlat(ammoData.ammoTDBID+t".objectActions",[t"ItemAction.Drop",t"ItemAction.Disassemble"]);
  235.             TweakDBManager.UpdateRecord(buyModID);
  236.             TweakDBManager.UpdateRecord(sellModID);
  237.             TweakDBManager.UpdateRecord(weightModID);
  238.             TweakDBManager.UpdateRecord(quantityModID);
  239.             TweakDBManager.UpdateRecord(ammoData.ammoTDBID);
  240.         }
  241.     }
  242.  
  243.     private final func ApplyHandSys(config:ref<AmmoLimiterConfig>,ammoTypes:array<String>) -> Void{
  244.         for ammoType in ammoTypes{
  245.             let ammoData=ALDataCache.GetCachedALData(ammoType,config);
  246.             let recordID=TDBID.Create("Ammo.Handicap"+ammoType+"AmmoPreset");
  247.             let limit=Equals(config.handModeSelected,handMode.Disabled)?99999:Equals(config.handModeSelected,handMode.Optimized)?ammoData.limit:ammoData.handLimit;
  248.             let min=Equals(config.handModeSelected,handMode.Disabled)?0:Equals(config.handModeSelected,handMode.Optimized)?0:ammoData.handMin;
  249.             let max=Equals(config.handModeSelected,handMode.Disabled)?0:Equals(config.handModeSelected,handMode.Optimized)?ammoData.limit/10:ammoData.handMax;
  250.             TweakDBManager.SetFlat(recordID+t".handicapLimit",limit);
  251.             TweakDBManager.SetFlat(recordID+t".handicapMinQty",min);
  252.             TweakDBManager.SetFlat(recordID+t".handicapMaxQty",max);
  253.             TweakDBManager.UpdateRecord(recordID);
  254.         }
  255.     }
  256.  
  257.     private final func ApplyAmmoBoxQties(config:ref<AmmoLimiterConfig>) -> Void{
  258.         let mappings=[
  259.             ["Handgun","AmmoLootTable_inline0"],
  260.             ["Shotgun","AmmoLootTable_inline1"],
  261.             ["Rifle","AmmoLootTable_inline2"],
  262.             ["SniperRifle","AmmoLootTable_inline3"]
  263.         ];
  264.         let i:Int32=0;
  265.         while i<ArraySize(mappings){
  266.             let ammoType=mappings[i][0];
  267.             let lootTableID=mappings[i][1];
  268.             let ammoData=ALDataCache.GetCachedALData(ammoType,config);
  269.             let recordID=TDBID.Create("Ammo."+lootTableID);
  270.             TweakDBManager.SetFlat(recordID+t".dropCountMin",ammoData.ammoBox/2);
  271.             TweakDBManager.SetFlat(recordID+t".dropCountMax",ammoData.ammoBox);
  272.             TweakDBManager.UpdateRecord(recordID);
  273.             i+=1;
  274.         }
  275.     }
  276. }
  277.  
  278. // ### SYSTÈME DE RAMASSAGE ###
  279. @wrapMethod(PlayerPuppet)
  280. protected cb func OnItemChangedEvent(evt:ref<ItemChangedEvent>) -> Bool{
  281.     let result=wrappedMethod(evt);
  282.     if evt.difference==0{return result;}
  283.     if !ItemID.IsValid(evt.itemID) || GameInstance.GetBlackboardSystem(this.GetGame()).Get(GetAllBlackboardDefs().UI_System).GetBool(GetAllBlackboardDefs().UI_System.IsInMenu){return result;}
  284.     if !Equals(TweakDBInterface.GetItemRecord(ItemID.GetTDBID(evt.itemID)).ItemType().Type(),gamedataItemType.Con_Ammo){return result;}
  285.     let ammoType=ALUtils.GetAmmoTypeFromID(evt.itemID);
  286.     if Equals(ammoType,""){return result;}
  287.     let config=ALSystem.GetConfig();
  288.     let ammoData=ALDataCache.GetCachedALData(ammoType,config);
  289.     let transactionSystem=GameInstance.GetTransactionSystem(GetGameInstance());
  290.     let curAmount=transactionSystem.GetItemQuantity(this,evt.itemID);
  291.     let effectiveLimit:Int32;
  292.     let isActiveAmmo=Equals(ammoType,ALUtils.GetActiveWeaponAmmoType(this));
  293.     if config.sleepingAmmoControl && !isActiveAmmo{
  294.         let addedAmount=evt.difference;
  295.         let preAmount=curAmount-addedAmount;
  296.         effectiveLimit=preAmount;
  297.     }else if isActiveAmmo && config.activeWeaponBonus>100{effectiveLimit=(ammoData.limit*config.activeWeaponBonus)/100;}else{effectiveLimit=ammoData.limit;}
  298.     if curAmount<=effectiveLimit{return result;}
  299.     let excess=curAmount-effectiveLimit;
  300.     if ammoData.ammoConv==0.0 && config.autoSell==0{
  301.         GameInstance.GetLootManager(GetGameInstance()).SpawnItemDropOfManyItems(this,[DropInstruction.Create(evt.itemID,excess)],n"playerDropBag",this.GetWorldPosition());
  302.         if config.messageDisplay{this.ALMessage(ToString(excess)+" "+GetLocalizedTextByKey(TweakDBInterface.GetItemRecord(ItemID.GetTDBID(evt.itemID)).DisplayName())+" "+GetLocalizedTextByKey(n"AmmoLimiter-Message-Dropped")+".");}
  303.     }else{
  304.         let totalComp=ammoData.ammoConv>0.0?Cast<Int32>(Cast<Float>(excess)*ammoData.ammoConv*0.01):0;
  305.         let totalEddies=config.autoSell>0?Cast<Int32>(Cast<Float>(excess*3*config.autoSell)*ammoData.priceMult*0.01):0;
  306.         if totalComp==0 && totalEddies==0{return result;}
  307.         let actualExcess=totalComp>0?Cast<Int32>(Cast<Float>(totalComp)/ammoData.ammoConv*100.0):excess;
  308.         transactionSystem.RemoveItem(this,evt.itemID,actualExcess);
  309.         let msg=config.messageDisplay?ToString(actualExcess)+" "+GetLocalizedTextByKey(TweakDBInterface.GetItemRecord(ItemID.GetTDBID(evt.itemID)).DisplayName())+" "+GetLocalizedTextByKey(n"AmmoLimiter-Message-Crafted")+" ":"";
  310.         if totalComp>0{
  311.             transactionSystem.GiveItem(this,ItemID.FromTDBID(t"Items.CommonMaterial1"),totalComp,[n"AmmoLimiter"]);
  312.             if config.messageDisplay{msg+=ToString(totalComp)+" "+GetLocalizedTextByKey(TweakDBInterface.GetItemRecord(t"Items.CommonMaterial1").DisplayName());}
  313.         }
  314.         if totalEddies>0{
  315.             transactionSystem.GiveItem(this,ItemID.FromTDBID(t"Items.money"),totalEddies,[n"AmmoLimiter"]);
  316.             if config.messageDisplay{msg+=(totalComp>0?"\\n+ ":"")+ToString(totalEddies)+" €$";}
  317.         }
  318.         if config.messageDisplay{this.ALMessage(msg+".");}
  319.     }
  320.     return result;
  321. }
  322.  
  323. // ### SYSTÈME DE DÉMONTAGE ###
  324. @wrapMethod(RPGManager)
  325. public final static func CanItemBeDisassembled(gameInstance:GameInstance,itemData:wref<gameItemData>) -> Bool{
  326.     let config=ALSystem.GetConfig();
  327.     return IsDefined(itemData) && config.ammoDisassDisabled && itemData.HasTag(n"Ammo")?false:wrappedMethod(gameInstance,itemData);
  328. }
  329.  
  330. @wrapMethod(DisassembleAction)
  331. public func CompleteAction(gameInstance:GameInstance) -> Void{
  332.     let itemData=this.GetItemData();
  333.     let config=ALSystem.GetConfig();
  334.     let executor=this.GetExecutor();
  335.     wrappedMethod(gameInstance);
  336.     if config.ammoDisass>0 && IsDefined(executor) && IsDefined(itemData){
  337.         let player=executor as PlayerPuppet;
  338.         if !IsDefined(player){return;}
  339.         let record=TweakDBInterface.GetItemRecord(ItemID.GetTDBID(itemData.GetID())) as WeaponItem_Record;
  340.         if !IsDefined(record){return;}
  341.         let maxAmmo=Cast<Int32>(GameInstance.GetStatsSystem(gameInstance).GetStatValue(Cast<StatsObjectID>(itemData.GetID()),gamedataStatType.MagazineCapacityBase))*config.ammoDisass/100;
  342.         if maxAmmo<=0{return;}
  343.         let ammoData=ALDataCache.GetCachedALData(ALUtils.GetAmmoTypeFromWeaponType(record.ItemType().Type()),config);
  344.         if Equals(ammoData.ammoTDBID,t""){return;}
  345.         let ammoAmount=RandRange(0,maxAmmo+1);
  346.         if ammoAmount>0{
  347.             GameInstance.GetTransactionSystem(gameInstance).GiveItem(player,ItemID.FromTDBID(ammoData.ammoTDBID),ammoAmount);
  348.             if config.messageDisplay{player.ALMessage(GetLocalizedTextByKey(n"AmmoLimiter-Message-Recovered")+" "+ToString(ammoAmount)+" "+GetLocalizedTextByKey(TweakDBInterface.GetItemRecord(ammoData.ammoTDBID).DisplayName())+".");}
  349.         }
  350.     }
  351. }
  352.  
  353. @wrapMethod(CraftingSystem)
  354. private func OnDisassembleItemRequest(request:ref<DisassembleItemRequest>) -> Void{
  355.     let config=ALSystem.GetConfig();
  356.     let itemData=GameInstance.GetTransactionSystem(this.GetGameInstance()).GetItemData(request.target,request.itemID);
  357.     if IsDefined(itemData) && itemData.HasTag(n"Ammo"){
  358.         let originalAmount=request.amount;
  359.         for ammoType in ALUtils.GetAmmoTypeNames(){
  360.             if Equals(ItemID.GetTDBID(itemData.GetID()),ALUtils.GetAmmoTDBID(ammoType)){
  361.                 let ammoData=ALDataCache.GetCachedALData(ammoType,config);
  362.                 let ammoPerComp=Cast<Float>(ammoData.ammoCraft)/Cast<Float>(config.craftingCompForAmmo);
  363.                 let requestedComps=FloorF(Cast<Float>(originalAmount)/ammoPerComp);
  364.                 if requestedComps>=1{
  365.                     let exactFloat=Cast<Float>(requestedComps)*ammoPerComp;
  366.                     let exactInt=Cast<Int32>(exactFloat);
  367.                     if Cast<Float>(exactInt)==exactFloat{request.amount=exactInt;}else{request.amount=requestedComps*CeilF(ammoPerComp);}
  368.                 }else{request.amount=0;}
  369.                 if request.amount>0{
  370.                     let removedEvent=new ItemBeingRemovedEvent();
  371.                     removedEvent.itemID=request.itemID;
  372.                     removedEvent.itemData=itemData;
  373.                     removedEvent.difference=request.amount;
  374.                     removedEvent.currentQuantity=0;
  375.                     let player=GameInstance.GetPlayerSystem(this.GetGameInstance()).GetLocalPlayerMainGameObject() as PlayerPuppet;
  376.                     player.QueueEvent(removedEvent);
  377.                 }
  378.                 break;
  379.             }
  380.         }
  381.     }
  382.     wrappedMethod(request);
  383. }
  384.  
  385. @wrapMethod(CraftingSystem)
  386. private func DisassembleItem(target:wref<GameObject>,itemID:ItemID,quantity:Int32) -> Void{
  387.     let itemData=GameInstance.GetTransactionSystem(this.GetGameInstance()).GetItemData(target,itemID);
  388.     if IsDefined(itemData) && itemData.HasTag(n"Ammo"){
  389.         let config=ALSystem.GetConfig();
  390.         for ammoType in ALUtils.GetAmmoTypeNames(){
  391.             if Equals(ItemID.GetTDBID(itemData.GetID()),ALUtils.GetAmmoTDBID(ammoType)){
  392.                 let restoredAttachments:array<ItemAttachments>;
  393.                 let vanillaResults=this.GetDisassemblyResultItems(target,itemID,1,restoredAttachments);
  394.                 if ArraySize(vanillaResults)>0{
  395.                     let ammoData=ALDataCache.GetCachedALData(ammoType,config);
  396.                     let correctComps=Cast<Int32>(Cast<Float>(quantity*config.craftingCompForAmmo)/Cast<Float>(ammoData.ammoCraft));
  397.                     GameInstance.GetTelemetrySystem(this.GetGameInstance()).LogItemDisassembled(target,itemID);
  398.                     let listOfIngredients:array<IngredientData>;
  399.                     if correctComps>0{
  400.                         GameInstance.GetTransactionSystem(this.GetGameInstance()).RemoveItem(target,itemID,quantity);
  401.                         GameInstance.GetTransactionSystem(this.GetGameInstance()).GiveItem(target,ItemID.FromTDBID(vanillaResults[0].id.GetID()),correctComps);
  402.                         let ingredient:IngredientData;
  403.                         ingredient.id=vanillaResults[0].id;
  404.                         ingredient.quantity=correctComps;
  405.                         ArrayPush(listOfIngredients,ingredient);
  406.                     }
  407.                     let Blackboard:ref<IBlackboard>=GameInstance.GetBlackboardSystem(this.GetGameInstance()).Get(GetAllBlackboardDefs().UI_Crafting);
  408.                     if IsDefined(Blackboard){
  409.                         Blackboard.SetVariant(GetAllBlackboardDefs().UI_Crafting.lastCommand,ToVariant(CraftingCommands.DisassemblingFinished),true);
  410.                         Blackboard.SetVariant(GetAllBlackboardDefs().UI_Crafting.lastItem,ToVariant(itemID),true);
  411.                         if ArraySize(listOfIngredients)>0{Blackboard.SetVariant(GetAllBlackboardDefs().UI_Crafting.lastIngredients,ToVariant(listOfIngredients),true);}
  412.                     }
  413.                     return;
  414.                 }
  415.             }
  416.         }
  417.     }
  418.     wrappedMethod(target,itemID,quantity);
  419. }
  420.  
  421. // ### FILTRES D’INVENTAIRE ###
  422. @wrapMethod(ItemCategoryFliter)
  423. public final static func FilterItem(filter:ItemFilterCategory,wrappedData:ref<WrappedInventoryItemData>) -> Bool{
  424.     if IsDefined(wrappedData.Item) && Equals(wrappedData.Item.GetItemType(),gamedataItemType.Con_Ammo){
  425.         let ammoCat=ALSystem.GetConfig().ammoCategorySelected;
  426.         return (Equals(ammoCat,ammoCategory.RangedWeapons) && (Equals(filter,ItemFilterCategory.RangedWeapons) || Equals(filter,ItemFilterCategory.AllItems))) || (Equals(ammoCat,ammoCategory.Attachments) && (Equals(filter,ItemFilterCategory.Attachments) || Equals(filter,ItemFilterCategory.AllItems))) || (Equals(ammoCat,ammoCategory.Consumables) && (Equals(filter,ItemFilterCategory.Consumables) || Equals(filter,ItemFilterCategory.Grenades) || Equals(filter,ItemFilterCategory.AllItems)));
  427.     }
  428.     return wrappedMethod(filter,wrappedData);
  429. }
  430.  
  431. @wrapMethod(CraftingMainLogicController)
  432. protected func SetupFilters() -> Void{
  433.     let ammoCat=ALSystem.GetConfig().ammoCategorySelected;
  434.     if Equals(ammoCat,ammoCategory.RangedWeapons){ArrayPush(this.m_filters,EnumInt(ItemFilterCategory.RangedWeapons));}else if Equals(ammoCat,ammoCategory.Attachments){ArrayPush(this.m_filters,EnumInt(ItemFilterCategory.Attachments));}else if Equals(ammoCat,ammoCategory.Consumables){ArrayPush(this.m_filters,EnumInt(ItemFilterCategory.Consumables));}
  435.     wrappedMethod();
  436. }
  437.  
  438. @wrapMethod(CraftingDataView)
  439. public func FilterItem(data:ref<IScriptable>) -> Bool{
  440.     let shouldShow=wrappedMethod(data);
  441.     if shouldShow{return true;}
  442.     let recipeData=data as RecipeData;
  443.     if IsDefined(recipeData){
  444.         let itemType=TweakDBInterface.GetItemRecord(recipeData.id.GetID()).ItemType().Type();
  445.         if !Equals(itemType,gamedataItemType.Con_Ammo){return false;}
  446.         let ammoCat=ALSystem.GetConfig().ammoCategorySelected;
  447.         let currentFilter=this.GetFilterType();
  448.         return (Equals(ammoCat,ammoCategory.RangedWeapons) && (Equals(currentFilter,ItemFilterCategory.RangedWeapons) || Equals(currentFilter,ItemFilterCategory.AllItems))) || (Equals(ammoCat,ammoCategory.Attachments) && (Equals(currentFilter,ItemFilterCategory.Attachments) || Equals(currentFilter,ItemFilterCategory.AllItems))) || (Equals(ammoCat,ammoCategory.Consumables) && (Equals(currentFilter,ItemFilterCategory.Consumables) || Equals(currentFilter,ItemFilterCategory.AllItems)));
  449.     }
  450.     return false;
  451. }
  452.  
  453. // ### AFFICHAGE DES MUNITIONS DANS L’INVENTAIRE ###
  454. @wrapMethod(UIInventoryItemsManager)
  455. public final static func GetBlacklistedTags() -> array<CName>{
  456.     let filteredTags=wrappedMethod();
  457.     ArrayRemove(filteredTags,n"Ammo");
  458.     return filteredTags;
  459. }
  460.  
  461. // ### SYSTÈME DE FABRICATION ###
  462. @wrapMethod(CraftingSystem)
  463. public final static func GetAmmoBulletAmount(ammoId:TweakDBID) -> Int32{
  464.     let ammoType=ALUtils.GetAmmoTypeFromID(ItemID.FromTDBID(ammoId));
  465.     return !Equals(ammoType,"")?ALDataCache.GetCachedALData(ammoType,ALSystem.GetConfig()).ammoCraft:wrappedMethod(ammoId);
  466. }
  467.  
  468. @wrapMethod(CraftingSystem)
  469. public final const func GetMaxCraftingAmount(itemData:wref<gameItemData>) -> Int32{
  470.     let itemRecord=TweakDBInterface.GetItemRecord(ItemID.GetTDBID(itemData.GetID()));
  471.     if !itemRecord.TagsContains(n"Ammo"){return wrappedMethod(itemData);}
  472.     let config=ALSystem.GetConfig();
  473.     let ammoData=ALDataCache.GetCachedALData(ALUtils.GetAmmoTypeFromID(itemData.GetID()),config);
  474.     let owner=this.m_playerCraftBook.GetOwner();
  475.     let transactionSystem=GameInstance.GetTransactionSystem(this.GetGameInstance());
  476.     let materialQuantity=transactionSystem.GetItemQuantity(owner,ItemID.FromTDBID(t"Items.CommonMaterial1"));
  477.     let currentQuantity=transactionSystem.GetItemQuantity(owner,itemData.GetID());
  478.     let materialLimit=materialQuantity>=config.craftingCompForAmmo?materialQuantity/config.craftingCompForAmmo:0;
  479.     let ammoLimit:Int32;
  480.     if currentQuantity+ammoData.ammoCraft<=ammoData.limit{ammoLimit=(ammoData.limit-currentQuantity)/ammoData.ammoCraft;}else{ammoLimit=9999;}
  481.     return Max(Min(materialLimit,ammoLimit),0);
  482. }
  483.  
  484. @wrapMethod(CraftingSystem)
  485. public final const func CanItemBeCrafted(itemData:wref<gameItemData>) -> Bool{
  486.     if !TweakDBInterface.GetItemRecord(ItemID.GetTDBID(itemData.GetID())).TagsContains(n"Ammo"){return wrappedMethod(itemData);}
  487.     let config=ALSystem.GetConfig();
  488.     let ammoData=ALDataCache.GetCachedALData(ALUtils.GetAmmoTypeFromID(itemData.GetID()),config);
  489.     let transactionSystem=GameInstance.GetTransactionSystem(this.GetGameInstance());
  490.     let owner=this.m_playerCraftBook.GetOwner();
  491.     if !this.HasIngredients(this.GetItemCraftingCost(itemData)){return false;}
  492.     if config.strictLimitation{
  493.         let currentQuantity=transactionSystem.GetItemQuantity(owner,itemData.GetID());
  494.         if currentQuantity+ammoData.ammoCraft>ammoData.limit{return false;}
  495.     }
  496.     return true;
  497. }
  498.  
  499. @wrapMethod(CraftingSystem)
  500. private final func CraftItem(target:wref<GameObject>,itemRecord:ref<Item_Record>,amount:Int32,opt ammoBulletAmount:Int32) -> wref<gameItemData>{
  501.     let isAmmo=itemRecord.TagsContains(n"Ammo");
  502.     if isAmmo{
  503.         let config=ALSystem.GetConfig();
  504.         let ammoType=ALUtils.GetAmmoTypeFromID(ItemID.FromTDBID(itemRecord.GetID()));
  505.         let ammoData=ALDataCache.GetCachedALData(ammoType,config);
  506.         let transactionSystem=GameInstance.GetTransactionSystem(this.GetGameInstance());
  507.         let craftedItemID=ItemID.FromTDBID(itemRecord.GetID());
  508.         transactionSystem.RemoveItemByTDBID(target,t"Items.CommonMaterial1",config.craftingCompForAmmo*amount,true);
  509.         let finalAmmoAmount=amount*ammoData.ammoCraft;
  510.         transactionSystem.GiveItem(target,craftedItemID,finalAmmoAmount);
  511.         this.ProcessCraftSkill(Cast<Float>(TweakDBInterface.GetInt(t"Constants.CraftingSystem.commonIngredientXP",10)*amount));
  512.         let itemData=transactionSystem.GetItemData(target,craftedItemID);
  513.         if IsDefined(itemData){
  514.             this.SetItemLevel(itemData);
  515.             this.MarkItemAsCrafted(itemData);
  516.         }
  517.         this.SendItemCraftedDataTrackingRequest(craftedItemID,finalAmmoAmount);
  518.         return itemData;
  519.     }
  520.     return wrappedMethod(target,itemRecord,amount,ammoBulletAmount);
  521. }
  522.  
  523. // ### SYSTÈME DE PICKER ###
  524. @wrapMethod(ItemQuantityPickerController)
  525. private func SetData() -> Void{
  526.     wrappedMethod();
  527.     if IsDefined(this.m_data){
  528.         let itemID=InventoryItemData.GetID(this.m_data.gameItemData);
  529.         if Equals(TweakDBInterface.GetItemRecord(ItemID.GetTDBID(itemID)).ItemType().Type(),gamedataItemType.Con_Ammo){
  530.             let ammoType=ALUtils.GetAmmoTypeFromID(itemID);
  531.             let ammoData=ALDataCache.GetCachedALData(ammoType,ALSystem.GetConfig());
  532.             this.UpdateAmmoDisplay(this.m_data.maxValue,ammoType,ammoData);
  533.         }
  534.     }
  535. }
  536.  
  537. @wrapMethod(ItemQuantityPickerController)
  538. protected cb func OnSliderValueChanged(sliderController:wref<inkSliderController>,progress:Float,value:Float) -> Bool{
  539.     let result=wrappedMethod(sliderController,progress,value);
  540.     if IsDefined(this.m_data){
  541.         let itemID=InventoryItemData.GetID(this.m_data.gameItemData);
  542.         if Equals(TweakDBInterface.GetItemRecord(ItemID.GetTDBID(itemID)).ItemType().Type(),gamedataItemType.Con_Ammo){
  543.             let ammoType=ALUtils.GetAmmoTypeFromID(itemID);
  544.             this.UpdateAmmoDisplay(Cast<Int32>(value),ammoType,ALDataCache.GetCachedALData(ammoType,ALSystem.GetConfig()));
  545.         }
  546.     }
  547.     return result;
  548. }
  549.  
  550. @wrapMethod(ItemQuantityPickerController)
  551. protected final func UpdateProgress() -> Void{
  552.     wrappedMethod();
  553.     if IsDefined(this.m_data){
  554.         let itemID=InventoryItemData.GetID(this.m_data.gameItemData);
  555.         if Equals(TweakDBInterface.GetItemRecord(ItemID.GetTDBID(itemID)).ItemType().Type(),gamedataItemType.Con_Ammo){
  556.             let ammoType=ALUtils.GetAmmoTypeFromID(itemID);
  557.             this.UpdateAmmoDisplay(this.m_choosenQuantity,ammoType,ALDataCache.GetCachedALData(ammoType,ALSystem.GetConfig()));
  558.         }
  559.     }
  560. }
  561.  
  562. @addMethod(ItemQuantityPickerController)
  563. private func UpdateAmmoDisplay(batchCount:Int32,ammoType:String,ammoData:ref<ALData>) -> Void{
  564.     if Equals(ammoType,""){return;}
  565.     let originalName=inkTextRef.GetText(this.m_itemNameText);
  566.     let parenPos=StrFindFirst(originalName," (");
  567.     let cleanName=parenPos>0?StrLeft(originalName,parenPos):originalName;
  568.     inkTextRef.SetText(this.m_itemNameText,cleanName+" ("+IntToString(batchCount*ammoData.ammoCraft)+" "+GetLocalizedTextByKey(n"AmmoLimiter-UI-Total")+")");
  569.     let totalWeight=Cast<Float>(batchCount)*ammoData.ammoWeight*Cast<Float>(ammoData.ammoCraft);
  570.     inkTextRef.SetText(this.m_weightText,FloatToStringPrec(totalWeight,2)+" ("+FloatToStringPrec(ammoData.ammoWeight,3)+" "+GetLocalizedTextByKey(n"AmmoLimiter-UI-Unit")+")");
  571. }
  572.  
  573. // ### SYSTÈME D'AVERTISSEMENT ###
  574. public static func CheckAndNotifyLowAmmo(player:ref<PlayerPuppet>,weapon:ref<WeaponObject>) -> Void{
  575.     let config=ALSystem.GetConfig();
  576.     if config.ammoLowWarning==0{return;}
  577.     let ammoID=WeaponObject.GetAmmoType(weapon);
  578.     let ammoType=ALUtils.GetAmmoTypeFromID(ammoID);
  579.     if Equals(ammoType,""){return;}
  580.     let ammoData=ALDataCache.GetCachedALData(ammoType,config);
  581.     let warningThreshold=Cast<Int32>(Cast<Float>(ammoData.limit)*Cast<Float>(config.ammoLowWarning)/100.0);
  582.     let transactionSystem=GameInstance.GetTransactionSystem(player.GetGame());
  583.     let currentAmmo=transactionSystem.GetItemQuantity(player,ammoID);
  584.     if currentAmmo<=warningThreshold && currentAmmo>0{
  585.         let ammoName=GetLocalizedTextByKey(TweakDBInterface.GetItemRecord(ItemID.GetTDBID(ammoID)).DisplayName());
  586.         let message=GetLocalizedTextByKey(n"AmmoLimiter-UI-LowAmmoWarning");
  587.         let finalMessage=StrReplace(message,"PROUTS",ammoName);
  588.         let simpleScreenMessage:SimpleScreenMessage;
  589.         simpleScreenMessage.isShown=true;
  590.         simpleScreenMessage.duration=1.2;
  591.         simpleScreenMessage.message=finalMessage;
  592.         simpleScreenMessage.isInstant=true;
  593.         GameInstance.GetBlackboardSystem(player.GetGame()).Get(GetAllBlackboardDefs().UI_Notifications).SetVariant(GetAllBlackboardDefs().UI_Notifications.WarningMessage,ToVariant(simpleScreenMessage),true);
  594.     }
  595. }
  596.  
  597. @wrapMethod(WeaponObject)
  598. public final static func SendAmmoUpdateEvent(weaponOwner:wref<GameObject>,weapon:wref<WeaponObject>) -> Void{
  599.     wrappedMethod(weaponOwner,weapon);
  600.     let player=weaponOwner as PlayerPuppet;
  601.     if IsDefined(player) && IsDefined(weapon){CheckAndNotifyLowAmmo(player,weapon);}
  602. }
  603.  
  604. @wrapMethod(PlayerPuppet)
  605. protected cb func OnItemAddedToSlot(evt:ref<ItemAddedToSlot>) -> Bool{
  606.     let result=wrappedMethod(evt);
  607.     if evt.GetSlotID()==t"AttachmentSlots.WeaponRight"{
  608.         let weapon=GameInstance.GetTransactionSystem(this.GetGame()).GetItemInSlot(this,evt.GetSlotID()) as WeaponObject;
  609.         if IsDefined(weapon){CheckAndNotifyLowAmmo(this,weapon);}
  610.     }
  611.     return result;
  612. }
  613.  
Advertisement
Add Comment
Please, Sign In to add comment