From ecabcc66607827dbcfd6f8ccd9ca59e5cab9b090 Mon Sep 17 00:00:00 2001
From: Arisaya <117544545+ArisayaDragon@users.noreply.github.com>
Date: Tue, 31 Mar 2026 19:10:37 -0700
Subject: [PATCH 1/4] feat: 106504: partial implementation
---
Transcendence/TransCore/HumanSpaceVol01.xml | 1 +
Transcendence/TransCore/Salvagers.xml | 245 +++++++++++++++++++-
2 files changed, 245 insertions(+), 1 deletion(-)
diff --git a/Transcendence/TransCore/HumanSpaceVol01.xml b/Transcendence/TransCore/HumanSpaceVol01.xml
index f8e009a0e..70a60331c 100644
--- a/Transcendence/TransCore/HumanSpaceVol01.xml
+++ b/Transcendence/TransCore/HumanSpaceVol01.xml
@@ -1737,6 +1737,7 @@
+
diff --git a/Transcendence/TransCore/Salvagers.xml b/Transcendence/TransCore/Salvagers.xml
index 08919064d..d8748b3a1 100644
--- a/Transcendence/TransCore/Salvagers.xml
+++ b/Transcendence/TransCore/Salvagers.xml
@@ -59,7 +59,7 @@
-
+
@@ -212,6 +212,249 @@
/>
+
+
+
+
+
+
+
+ (cat '001000C4_ sourceID '_marked)
+
+
+ 'search
+
+
+
+
+
+ (block
+ (
+ (statusVar '001000C4_status)
+ (sourceID (objGetID gSource))
+
+ ; salvager nomad clans dont coordinate so they
+ ; will waste time looking at wrecks other nomads
+ ; have looked at
+
+ (lootedVar (@obj gSource 'lootedVar))
+
+ ; This is the number of wares at which they will set up shop
+
+ (maxWares 50)
+
+ ; state tracking vars
+
+ (state (obj@ gSource statusVar))
+ (setState (lambda (newState) (objSet@ gSource statusVar newState)))
+ (startNewSearch (lambda () (block () (setState 'initSearch) (shpOrder gSource '))))
+ (dockedAt (shpGetDockObj gSource))
+
+ ; our loot for sale - we calculate this later if needed
+
+ allLoot
+ )
+ (switch
+
+ ; if we are searching for lootable wrecks...
+ (eq status 'search)
+ (block
+ (
+ (allWrecks (rpgFindWrecksToSalvage gSource lootedVar))
+ )
+ (if allWrecks
+ ; Begin salvaging nearby wrecks
+ (block
+ (
+ (theWreck (random allWrecks))
+ )
+ ; Cancel current oreders
+ (shpCancelOrders gSource)
+
+ ; We are now in the salvage state
+ ; Need to set the correct state and order
+ (obj@ gSource statusVar 'salvage)
+ (shpOrder gSource 'dock theWreck)
+ )
+ ; Otherwise keep searching
+ (block
+ (
+ (thePos (sysVectorRandom ))
+ )
+ )
+ )
+ )
+
+ ; if we are actively salvaging something
+ (eq status 'salvage)
+ (switch
+ ; If we are docked with something that is lootable, loot it
+ (and dockedAt
+ (not (objMatches dockedAt gSource "sTA"))
+ (setq allLoot (objGetItems gSource "*~mf U"))
+ )
+ (block ()
+ (enum allLoot theItem (block () (objRemoveItem dockedAt theItem) (objAddItem gSource theItem)))
+ (setState 'search)
+ )
+ ; If we are docked at an empty wreck or something that
+ ; we shouldnt be - this can potentially happen due to
+ ; other scripts or mods - we need to undock and go back to searching
+ dockedAt
+ )
+ (block
+ (
+ ; Get all item stacks
+ (currentWares (objGetItems gSource "U"))
+ (numWares (count currentWares))
+ remainingWrecks
+ )
+ (if (gr numWares maxWares))
+ )
+
+ ; If we dont have a valid status, we need to re-initialize
+ (block ()
+ (setState 'search)
+ (shp)
+ (shpOrderImmediate gSource 'wait 1)
+ )
+ )
+
+ ; If we're docked at an object...
+ (if (and dockedAt
+ (objMatches dockedAt gSource "sTA +populated +salvagerBazaar")
+
+ ; Compose a list of all loot on board that the station
+ ; might want to buy from us.
+ )
+
+ ; To do - implement shop code
+
+ ; We loot wrecks and process the goods
+ (if (and (not (objMatches dockedAt "sTA"))
+
+ ; Compose a list of all loot on board that the station
+ ; might want to buy from us.
+
+ (setq allLoot (filter (objGetItems gSource "*~mf U") theItem
+ (objGetBuyPrice dockedAt theItem)
+ ))
+ )
+ (block Nil
+ (enum allLoot theItem (objRemoveItem gSource theItem))
+ (enum allLoot theItem (objAddItem dockedAt theItem))
+ )
+
+ ; Otherwise we docked at something random
+ ; we dont loot non-wreck objects
+ ()
+ )
+ )
+
+ ; Figure out what to do next
+ (switch
+ (eq status 'enteredSystem)
+ (block Nil
+ (setq theTarget (random (sysFindObject gSource "T +arcology")))
+ (shpOrder gSource 'orbit (sysFindObject Nil "TNV +stKatsArcology;") 35 (random 20 40))
+ (shpOrder gSource 'dock theTarget)
+ (shpOrder gSource 'waitForThreat (random 10 60))
+ (objSetData gSource statusVar 'dockedAtNewVictoria)
+ )
+
+ (eq status 'dockedAtNewVictoria)
+ (block (roll allWrecks)
+ ; When leaving new victoria, orbit around for a bit
+ (shpOrder gSource 'orbit (sysFindObject Nil "TNV +stKatsArcology;") 35 (random 20 40))
+
+ ; Randomly choose a path
+ (setq roll (random 1 100))
+ (switch
+ ; Gate out
+ (leq roll 30)
+ (block Nil
+ (shpOrder gSource 'gate)
+ (objSetData gSource statusVar 'leavingSystem)
+ )
+
+ ; If there are wrecks in the area, loot them
+ (and (rpgFilterSalvager gSource)
+
+ ; Compose a list of all wrecks in the area
+
+ (setq allWrecks (rpgFindWrecksToSalvage gSource lootedVar))
+ )
+ (block ()
+ (rpgInitSalvageAndScuttleOperation gSource allWrecks lootedVar)
+ (objSetData gSource statusVar 'dockedAtStation)
+ )
+
+ ; Dock at a random station in the system
+ (block (theTarget)
+ (setq theTarget (random (sysFindObject gSource "TAF +populated; -arcology; -occupation;")))
+ (shpOrder gSource 'dock theTarget)
+ (shpOrder gSource 'waitForThreat (random 10 20))
+ (objSetData gSource statusVar 'dockedAtStation)
+ )
+ )
+ )
+
+ (eq status 'dockedAtStation)
+ (block (roll allWrecks)
+ ; Randomly choose a path
+ (setq roll (random 1 100))
+ (switch
+ ; Gate out
+ (leq roll 30)
+ (block Nil
+ (shpOrder gSource 'gate)
+ (objSetData gSource statusVar 'leavingSystem)
+ )
+
+ ; If there are wrecks in the area, loot them
+ (and (rpgFilterSalvager gSource)
+
+ ; Compose a list of all wrecks in the area
+
+ (setq allWrecks (rpgFindWrecksToSalvage gSource lootedVar))
+ )
+ (block ()
+ (rpgInitSalvageAndScuttleOperation gSource allWrecks lootedVar)
+ (objSetData gSource statusVar 'dockedAtStation)
+ )
+
+ ; Dock at new victoria
+ (leq roll 80)
+ (block (theTarget)
+ (setq theTarget (random (sysFindObject gSource "T +arcology")))
+ (shpOrder gSource 'orbit (sysFindObject Nil "TNV +stKatsArcology;") 35 (random 20 40))
+ (shpOrder gSource 'dock theTarget)
+ (shpOrder gSource 'waitForThreat (random 10 60))
+ (objSetData gSource statusVar 'dockedAtNewVictoria)
+ )
+
+ ; Dock at a random station in the system
+ (block (theTarget)
+ (setq theTarget (random (sysFindObject gSource "TAF +populated; -arcology; -occupation;")))
+ (shpOrder gSource 'dock theTarget)
+ (shpOrder gSource 'waitForThreat (random 10 20))
+ (objSetData gSource statusVar 'dockedAtStation)
+ )
+ )
+ )
+ )
+
+ ; If we were docked at an object that we just looted, then destroy the object
+ (rpgImplementScuttleSalvagedWreck gSource dockedAt lootedVar)
+ )
+
+
+
From 80c2708b75878af7c7942fe8483cd58d853996fc Mon Sep 17 00:00:00 2001
From: Arisaya <117544545+ArisayaDragon@users.noreply.github.com>
Date: Wed, 1 Apr 2026 14:33:36 -0700
Subject: [PATCH 2/4] feat: 106504: additional implementation
---
Transcendence/TransCore/Salvagers.xml | 45 +++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 3 deletions(-)
diff --git a/Transcendence/TransCore/Salvagers.xml b/Transcendence/TransCore/Salvagers.xml
index d8748b3a1..0c35b42e1 100644
--- a/Transcendence/TransCore/Salvagers.xml
+++ b/Transcendence/TransCore/Salvagers.xml
@@ -229,6 +229,19 @@
'search
+
+
+
+ (block
+ (
+ (centerMarker (sysCreateMarker 'tempMeasuringMarker ()))
+ (farthestObject (sysFindObject centerMarker "t R"))
+ (farthestDistance (sysVectorDistance (objGetPos farthestObject) (objGetPos centerMarker)))
+ )
+ (objRemove centerMarker)
+ farthestDistance
+ )
+
@@ -284,8 +297,9 @@
; Otherwise keep searching
(block
(
- (thePos (sysVectorRandom ))
+ (thePos (sysVectorRandom () (obj@ gSource 'farthestDistance)))
)
+ (shpOrder gSource 'gotoPos thePos)
)
)
)
@@ -314,13 +328,38 @@
(numWares (count currentWares))
remainingWrecks
)
- (if (gr numWares maxWares))
+ (if (gr numWares maxWares)
+ ; If we have enough wares, we setup shop
+ )
+ )
+
+ ; if we are currently a shop
+ (eq status 'shop)
+ (block
+ (
+ (currentWares (objGetItems gSource "U"))
+ (numWares (count currentWares))
+ (timeAsShop (- (unvGetTick) (obj@ gSource 'timeSetupShop)))
+ )
+ (if (or (ls timeAsShop 0) (gr timeAsShop 1800) (= numWares 0))
+ (if (gr numWares 0)
+ ; Send ships to cleanup
+ (block ()
+ )
+ ; otherwise just resume searching
+ (block ()
+ )
+ )
+ ; otherwise we remain a shop
+ (block ()
+ )
+ )
)
; If we dont have a valid status, we need to re-initialize
(block ()
(setState 'search)
- (shp)
+ (shpCancelOrders gSource)
(shpOrderImmediate gSource 'wait 1)
)
)
From 71405be89784aa0d916fb9ad459b9c4520c6989c Mon Sep 17 00:00:00 2001
From: Arisaya <117544545+ArisayaDragon@users.noreply.github.com>
Date: Wed, 15 Apr 2026 13:34:53 -0700
Subject: [PATCH 3/4] feat: 106504: additional implementation of better
salvagers including shop system
---
Transcendence/TransCore/Salvagers.xml | 365 +++++++++++++++++++-------
1 file changed, 263 insertions(+), 102 deletions(-)
diff --git a/Transcendence/TransCore/Salvagers.xml b/Transcendence/TransCore/Salvagers.xml
index 0c35b42e1..50328b7e4 100644
--- a/Transcendence/TransCore/Salvagers.xml
+++ b/Transcendence/TransCore/Salvagers.xml
@@ -159,6 +159,157 @@
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (scrShowScreen gScreen &dsRPGCommoditiesExchangeBuy;)
+
+
+
+ (scrShowScreen gScreen &dsRPGCommoditiesExchangeSell;)
+
+
+
+
+
+ (rpgDockServices gPlayerShip)
+
+
+
+
+
+
+
+
+
+
+
+ (block Nil
+ (objSetData gSource 'customIntroDone True)
+ (scrShowPane gScreen "Default")
+ (scrShowScreen gScreen &dsTinkerCustomWork; {
+ criteria: "* +hasComponents:true; +tinkers;"
+ })
+ )
+
+
+
+
+
+
+
+
+
+
+ (block (
+ ; Figure out how much it would cost to make the ship immune to radiation
+ (cost (* 400 (shpGetArmorCount gPlayerShip)))
+ )
+
+ (if (geq (plyGetCredits gPlayer) cost)
+ (scrSetDescTranslate gScreen 'descDecon { cost:(fmtCurrency 'credit cost) })
+ (scrSetDescTranslate gScreen 'descDeconCantAfford)
+ )
+ (scrSetData gScreen 'deconCost cost)
+ (scrEnableAction gScreen 'actionDecon (geq (plyGetCredits gPlayer) cost))
+ )
+
+
+
+
+ (block (
+ (cost (scrGetData gScreen 'deconCost))
+ (armorEnhanced 0)
+ )
+ ; Decontaminate
+ (plyCharge gPlayer cost)
+ (shpDecontaminate gPlayerShip)
+
+ ; Make immune
+ (objEnumItems gPlayerShip "aI" theItem
+ (block (result)
+ (setq result (shpEnhanceItem gPlayerShip theItem {
+ enhancement: "+immunity:radiation"
+ type: &itRadiationImmuneCoating;
+ }))
+
+ (switch
+ (or (eq result 0) (eq result 2) (eq result 6) (eq result 7))
+ (setq armorEnhanced (add armorEnhanced 1))
+ )
+ )
+ )
+
+ ; Compose the result
+ (switch
+ (= armorEnhanced (shpGetArmorCount gPlayerShip))
+ (scrSetData gScreen 'deconResult 'descDeconImmune)
+
+ (= armorEnhanced 0)
+ (scrSetData gScreen 'deconResult 'descDeconNotImmune)
+
+ (scrSetData gScreen 'deconResult 'descDeconPartialImmune)
+ )
+
+ (scrShowPane gScreen "DeconDone")
+ )
+
+
+
+ (scrExitScreen gScreen 'forceUndock)
+
+
+
+
+
+
+
+ (scrSetDescTranslate gScreen (scrGetData gScreen 'deconResult))
+
+
+
+
+ (scrShowScreen gScreen "Main")
+
+
+
+
+
+
+
@@ -231,6 +382,8 @@
+
+
(block
(
@@ -242,10 +395,45 @@
farthestDistance
)
+
+ (random 5 15)
+
-
-
+
+
+ (objFireEvent gSource 'ev.behavior)
+
+
+ (objFireEvent gSource 'ev.behavior)
+
+
+ (if (and (objGetData aObjDocked '001000C4_customer) (= aDockTarget gSource))
+ (block
+ (
+ (currentWares (objGetItems gSource "U"))
+ (numWares (count currentWares))
+ (itemsMoved 0)
+ (targetPurchaseAmount (typ@ gType 'customerPurchaseQuantity))
+ )
+ (if currentWares
+ (enum currentWares (ls itemsMoved targetPurchaseAmount) theItem
+ (block
+ (
+ (quantity (min (itmGetCount theItem) targetPurchaseAmount))
+ )
+ (objAddItem aObjDocked theItem quantity)
+ (objRemoveItem gSource theItem quantity)
+ (setq itemsMoved (+ itemsMoved quantity))
+ )
+ )
+ )
+ (shpOrder aObjDocked 'wait 180)
+ (shpOrder aObjDocked 'gate)
+ )
+ )
+
+
(block
(
(statusVar '001000C4_status)
@@ -265,7 +453,7 @@
(state (obj@ gSource statusVar))
(setState (lambda (newState) (objSet@ gSource statusVar newState)))
- (startNewSearch (lambda () (block () (setState 'initSearch) (shpOrder gSource '))))
+ (checkBehaviorIn (lambda (ticks) (sysAddObjTimerEvent ticks gSource 'ev.behavior)))
(dockedAt (shpGetDockObj gSource))
; our loot for sale - we calculate this later if needed
@@ -330,6 +518,20 @@
)
(if (gr numWares maxWares)
; If we have enough wares, we setup shop
+ (block ()
+ ; Prepare for shop state
+
+ (setState 'shop)
+ (checkBehaviorIn 1800)
+
+ ; Clear any existing orders
+
+ (shpCancelOrders gSource)
+
+ ; Hold position to be a shop
+
+ (shpOrder gSource 'hold )
+ )
)
)
@@ -341,17 +543,68 @@
(numWares (count currentWares))
(timeAsShop (- (unvGetTick) (obj@ gSource 'timeSetupShop)))
)
- (if (or (ls timeAsShop 0) (gr timeAsShop 1800) (= numWares 0))
+ (if (or (ls timeAsShop 0) (gr timeAsShop 18000) (= numWares 0))
(if (gr numWares 0)
- ; Send ships to cleanup
- (block ()
+
+ ; Send ships to cleanup inventory
+
+ (block
+ (
+ (customerIds (obj@ gSource 'customers))
+ (customers (map customerIds 'excludeNil customerId (objGetObjectByID customerId)))
+ (customersAlive (map customers 'excludeNil customer (if (objMatches customer "SA") customer)))
+ )
+ (if customersAlive
+ ; we wait until they have been destroyed or left the system or bought all our goods
+ (checkBehaviorIn 1800)
+ ; Otherwise we need to create customers to buy our wares
+ (block
+ (
+ (nearestGate (sysFindObject gSource "G N"))
+ (newCustomers (map (make 'sequence 5) 'excludeNil i (sysCreateShip &tbCommPrivateCrafts; nearestGate &svIndependent;)))
+ (newCustomerIds (map newCustomers newCustomer (objGetID newCustomer)))
+ )
+
+ ; Register for events so we can tell when they dock
+
+ (objRegisterForEvents gSource newCustomers)
+
+ ; setup the customers
+
+ (enum newCustomers newCustomer
+ (block ()
+ ; Clear any existing orders
+ (shpCancelOrders newCustomer)
+
+ ; Tag them as a customer
+
+ (objSetData newCustomer '001000C4_customer 1)
+
+ ; First have them spread out a little bit
+
+ (shpOrder newCustomer 'approach (sysVectorRandom (objGetPos newCustomer) 100 20))
+
+ ; Then have them go shop
+
+ (shpOrder newCustomer 'dock gSource)
+ )
+ )
+ (objSet@ gSource 'customers newCustomerIds)
+ )
+ )
)
- ; otherwise just resume searching
+
+ ; otherwise resume searching for new wares
+
(block ()
+ (setState 'search)
+ (shpCancelOrders gSource)
+ (shpOrder gSource 'wait 1)
)
)
; otherwise we remain a shop
(block ()
+ (checkBehaviorIn 1800)
)
)
)
@@ -360,7 +613,8 @@
(block ()
(setState 'search)
(shpCancelOrders gSource)
- (shpOrderImmediate gSource 'wait 1)
+ (shpOrder gSource 'wait 1)
+ (objSet@ gSource 'timeSetupShop ())
)
)
@@ -394,104 +648,11 @@
()
)
)
-
- ; Figure out what to do next
- (switch
- (eq status 'enteredSystem)
- (block Nil
- (setq theTarget (random (sysFindObject gSource "T +arcology")))
- (shpOrder gSource 'orbit (sysFindObject Nil "TNV +stKatsArcology;") 35 (random 20 40))
- (shpOrder gSource 'dock theTarget)
- (shpOrder gSource 'waitForThreat (random 10 60))
- (objSetData gSource statusVar 'dockedAtNewVictoria)
- )
-
- (eq status 'dockedAtNewVictoria)
- (block (roll allWrecks)
- ; When leaving new victoria, orbit around for a bit
- (shpOrder gSource 'orbit (sysFindObject Nil "TNV +stKatsArcology;") 35 (random 20 40))
-
- ; Randomly choose a path
- (setq roll (random 1 100))
- (switch
- ; Gate out
- (leq roll 30)
- (block Nil
- (shpOrder gSource 'gate)
- (objSetData gSource statusVar 'leavingSystem)
- )
-
- ; If there are wrecks in the area, loot them
- (and (rpgFilterSalvager gSource)
-
- ; Compose a list of all wrecks in the area
-
- (setq allWrecks (rpgFindWrecksToSalvage gSource lootedVar))
- )
- (block ()
- (rpgInitSalvageAndScuttleOperation gSource allWrecks lootedVar)
- (objSetData gSource statusVar 'dockedAtStation)
- )
-
- ; Dock at a random station in the system
- (block (theTarget)
- (setq theTarget (random (sysFindObject gSource "TAF +populated; -arcology; -occupation;")))
- (shpOrder gSource 'dock theTarget)
- (shpOrder gSource 'waitForThreat (random 10 20))
- (objSetData gSource statusVar 'dockedAtStation)
- )
- )
- )
-
- (eq status 'dockedAtStation)
- (block (roll allWrecks)
- ; Randomly choose a path
- (setq roll (random 1 100))
- (switch
- ; Gate out
- (leq roll 30)
- (block Nil
- (shpOrder gSource 'gate)
- (objSetData gSource statusVar 'leavingSystem)
- )
-
- ; If there are wrecks in the area, loot them
- (and (rpgFilterSalvager gSource)
-
- ; Compose a list of all wrecks in the area
-
- (setq allWrecks (rpgFindWrecksToSalvage gSource lootedVar))
- )
- (block ()
- (rpgInitSalvageAndScuttleOperation gSource allWrecks lootedVar)
- (objSetData gSource statusVar 'dockedAtStation)
- )
-
- ; Dock at new victoria
- (leq roll 80)
- (block (theTarget)
- (setq theTarget (random (sysFindObject gSource "T +arcology")))
- (shpOrder gSource 'orbit (sysFindObject Nil "TNV +stKatsArcology;") 35 (random 20 40))
- (shpOrder gSource 'dock theTarget)
- (shpOrder gSource 'waitForThreat (random 10 60))
- (objSetData gSource statusVar 'dockedAtNewVictoria)
- )
-
- ; Dock at a random station in the system
- (block (theTarget)
- (setq theTarget (random (sysFindObject gSource "TAF +populated; -arcology; -occupation;")))
- (shpOrder gSource 'dock theTarget)
- (shpOrder gSource 'waitForThreat (random 10 20))
- (objSetData gSource statusVar 'dockedAtStation)
- )
- )
- )
- )
; If we were docked at an object that we just looted, then destroy the object
(rpgImplementScuttleSalvagedWreck gSource dockedAt lootedVar)
)
-
+
From 9a3772521937292614670b2904d55afd1b37ba30 Mon Sep 17 00:00:00 2001
From: Arisaya <117544545+ArisayaDragon@users.noreply.github.com>
Date: Wed, 22 Apr 2026 14:51:19 -0700
Subject: [PATCH 4/4] fix: 106504: additional fixes to salvager controller
---
Transcendence/TransCore/Salvagers.xml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Transcendence/TransCore/Salvagers.xml b/Transcendence/TransCore/Salvagers.xml
index 50328b7e4..a549ceacc 100644
--- a/Transcendence/TransCore/Salvagers.xml
+++ b/Transcendence/TransCore/Salvagers.xml
@@ -443,7 +443,7 @@
; will waste time looking at wrecks other nomads
; have looked at
- (lootedVar (@obj gSource 'lootedVar))
+ (lootedVar (obj@ gSource 'lootedVar))
; This is the number of wares at which they will set up shop
@@ -463,7 +463,7 @@
(switch
; if we are searching for lootable wrecks...
- (eq status 'search)
+ (eq state 'search)
(block
(
(allWrecks (rpgFindWrecksToSalvage gSource lootedVar))
@@ -493,7 +493,7 @@
)
; if we are actively salvaging something
- (eq status 'salvage)
+ (eq state 'salvage)
(switch
; If we are docked with something that is lootable, loot it
(and dockedAt
@@ -536,7 +536,7 @@
)
; if we are currently a shop
- (eq status 'shop)
+ (eq state 'shop)
(block
(
(currentWares (objGetItems gSource "U"))