Skip to content

Commit

Permalink
Rework xeno guaranteed slots logic and Fix thunderdome evolution slot…
Browse files Browse the repository at this point in the history
… bug (#4206)

# About the pull request

This PR reworks the logic regarding guaranteed xeno slots. Before, the
issue was that there was a discrepancy between gibbing/deletion and
regular death (meaning not getting gibbed wouldn't free up a free slot).
Now that logic is unified via using hive.remove_xeno and the
used_free_slots now is just a count of slots used for a caste rather
than trying to keep the calculation always correct. This avoids the
messiness of handing the free slot usage to say the other burrower when
there are two rather than one then freeing a slot.

Additionally, I encountered a bug during testing where evolution in the
thunderdome would alter a hive's slots (and the effect would only show
in hive_status after a xeno count update on add/removal), but that is
also resolved.

See Testing section below to confirm logic, see reproduction for the
t-dome fix, and then retesting.

# Explain why it's good for the game

Should fix #398 

# Testing Photographs and Procedure
<details>
<summary>Steps 1-9:</summary>

1: Initial hive spawned in:

![1](https://github.com/cmss13-devs/cmss13/assets/76988376/fd5a453d-42a2-4ecf-8f63-c2d4dc97d7ff)

2: Evo a drone to burrower (free slot used):

![2](https://github.com/cmss13-devs/cmss13/assets/76988376/ce243339-854b-42b8-8a97-f81307548886)

3: Evo another drone to burrower (tier 2 slot used):

![3](https://github.com/cmss13-devs/cmss13/assets/76988376/cd03c6ee-8560-45a7-900b-163225806966)

4: First burrower is killed:

![4](https://github.com/cmss13-devs/cmss13/assets/76988376/0b802d07-58c0-48bd-9a55-2d2606cd6148)

5: Second burrower is gibbed:

![5](https://github.com/cmss13-devs/cmss13/assets/76988376/df0786db-a64d-46bc-abfc-18724baadd31)

6: Evo another drone to burrower (free slot used - I also tried deleting
the burrower corpse afterwards to see if it affected anything):

![6](https://github.com/cmss13-devs/cmss13/assets/76988376/ba747571-cc21-4547-a844-a675874f7ff1)

7: Evo a drone to hivelord (free slot used):

![7](https://github.com/cmss13-devs/cmss13/assets/76988376/df1c9f9e-e615-4e86-aaf0-6088d109b1a6)

8: Spawned a carrier and drone in t-dome, and evolved that drone to
carrier (no effect on hive slots):

![8](https://github.com/cmss13-devs/cmss13/assets/76988376/6a9ac50f-d31e-40fc-9aa1-22a92454dc4b)

9: Killed and gibbed the t-dome carriers (no effect on hive slots):

![9](https://github.com/cmss13-devs/cmss13/assets/76988376/b2dbccb3-2a09-4669-9593-4c3eb87214f2)

---
</details>

<details>
<summary>Steps 10-14 Before thunderdome fix:</summary>

10: !! De-evolve a drone to larva **(t2 slots went down - unintended)**:
!!

![10](https://github.com/cmss13-devs/cmss13/assets/76988376/19b2d578-8ff3-4362-811a-aec45b7d1e2d)

11: !! Evolve larva to runner **(no effect on hive slots - unintended or
should have restored to slot counts in previous step)**: !!

![11](https://github.com/cmss13-devs/cmss13/assets/76988376/c5d4cde3-c819-42bf-b016-ae66bcd3ed85)

12: Evolve runner to lurker and correctly failed attempt to evolve to
ravager (t2 slot used):

![12](https://github.com/cmss13-devs/cmss13/assets/76988376/fafe2e58-dd8c-4c27-ad56-884fff755acc)

13: Evolve another drone to burrower (last tier 2 slot used):

![13](https://github.com/cmss13-devs/cmss13/assets/76988376/84e0b82b-2962-49ba-9491-444059fa3a93)

14: Correctly failed attempt to evolve to hivelord, but successful
evolution from drone to carrier (last guaranteed slot used):

![14](https://github.com/cmss13-devs/cmss13/assets/76988376/df898858-fcad-4b2a-ab10-8e9c262ab50a)

---
</details>

<details>
<summary>Steps 10-15 After thunderdome fix:</summary>

Steps 1-9 are identical.

10: De-evolve a drone to larva (correctly didn't change slot values
because of tdome evolution):

![new10](https://github.com/cmss13-devs/cmss13/assets/76988376/a51083f4-7ac7-47b1-8710-b9d740ea1f9e)

11: Evolve larva to runner (no effect on slots):

![new11](https://github.com/cmss13-devs/cmss13/assets/76988376/ae547ef6-a846-4936-97d8-e116d284c45c)

12: Evolve runner to lurker and correctly failed attempt to evolve to
ravager (t2 slot used):

![new12](https://github.com/cmss13-devs/cmss13/assets/76988376/b858823e-8611-4db9-ab76-60fece28e46b)

13: Evolve another drone to burrower (tier 2 slot used):

![new13](https://github.com/cmss13-devs/cmss13/assets/76988376/f1044827-df38-4d40-9d82-2737a09e5ffc)

14: Evolve another drone to burrower (last tier 2 slot used):

![new14](https://github.com/cmss13-devs/cmss13/assets/76988376/e1ea916c-b001-4d0e-973c-fc49de7ec419)

15: Correctly failed attempt to evolve to hivelord, but successful
evolution from drone to carrier (last guaranteed slot used):

![new15](https://github.com/cmss13-devs/cmss13/assets/76988376/4214ace4-8202-4b68-b526-f1ac5aae1e24)

</details>


# Changelog
:cl: Drathek
fix: Fix/Rework logic regarding xeno guaranteed slots
fix: Fix evolution in thunder dome affecting hive slots
/:cl:
  • Loading branch information
Drulikar authored Sep 16, 2023
1 parent 0917cd0 commit b7ec827
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 52 deletions.
39 changes: 22 additions & 17 deletions code/modules/mob/living/carbon/xenomorph/Evolution.dm
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,13 @@
qdel(new_xeno)
return

switch(new_xeno.tier) //They have evolved, add them to the slot count
if(2)
hive.tier_2_xenos |= new_xeno
if(3)
hive.tier_3_xenos |= new_xeno
var/area/xeno_area = get_area(new_xeno)
if(!is_admin_level(new_xeno.z) || (xeno_area.flags_atom & AREA_ALLOW_XENO_JOIN))
switch(new_xeno.tier) //They have evolved, add them to the slot count IF they are in regular game space
if(2)
hive.tier_2_xenos |= new_xeno
if(3)
hive.tier_3_xenos |= new_xeno

log_game("EVOLVE: [key_name(src)] evolved into [new_xeno].")
if(mind)
Expand Down Expand Up @@ -355,24 +357,27 @@

/mob/living/carbon/xenomorph/proc/can_evolve(castepick, potential_queens)
var/selected_caste = GLOB.xeno_datum_list[castepick]?.type
var/free_slots = LAZYACCESS(hive.free_slots, selected_caste)
if(free_slots)
var/free_slot = LAZYACCESS(hive.free_slots, selected_caste)
var/used_slot = LAZYACCESS(hive.used_slots, selected_caste)
if(free_slot > used_slot)
return TRUE

var/burrowed_factor = min(hive.stored_larva, sqrt(4*hive.stored_larva))
burrowed_factor = round(burrowed_factor)

var/used_tier_2_slots = length(hive.tier_2_xenos)
var/used_tier_3_slots = length(hive.tier_3_xenos)
for(var/caste_path in hive.used_free_slots)
if(!hive.used_free_slots[caste_path])
for(var/caste_path in hive.free_slots)
var/slots_free = hive.free_slots[caste_path]
var/slots_used = hive.used_slots[caste_path]
if(!slots_used)
continue
var/datum/caste_datum/C = caste_path
switch(initial(C.tier))
if(2) used_tier_2_slots--
if(3) used_tier_3_slots--
var/datum/caste_datum/current_caste = caste_path
switch(initial(current_caste.tier))
if(2)
used_tier_2_slots -= min(slots_used, slots_free)
if(3)
used_tier_3_slots -= min(slots_used, slots_free)

var/totalXenos = burrowed_factor
var/burrowed_factor = min(hive.stored_larva, sqrt(4*hive.stored_larva))
var/totalXenos = round(burrowed_factor)
for(var/mob/living/carbon/xenomorph/xeno as anything in hive.totalXenos)
if(xeno.counts_for_slots)
totalXenos++
Expand Down
17 changes: 2 additions & 15 deletions code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
Original file line number Diff line number Diff line change
Expand Up @@ -499,11 +499,7 @@
// Only handle free slots if the xeno is not in tdome
if(!is_admin_level(z))
var/selected_caste = GLOB.xeno_datum_list[caste_type]?.type
var/free_slots = LAZYACCESS(hive.free_slots, selected_caste)
if(free_slots)
hive.free_slots[selected_caste]--
var/new_val = LAZYACCESS(hive.used_free_slots, selected_caste) + 1
LAZYSET(hive.used_free_slots, selected_caste, new_val)
hive.used_slots[selected_caste]++

if(round_statistics && !statistic_exempt)
round_statistics.track_new_participant(faction, 1)
Expand Down Expand Up @@ -706,16 +702,7 @@
hive.remove_hive_leader(src, light_mode = TRUE)
SStracking.stop_tracking("hive_[hivenumber]", src)

// Only handle free slots if the xeno is not in tdome
if(!is_admin_level(z))
var/selected_caste = GLOB.xeno_datum_list[caste_type]?.type
var/used_slots = LAZYACCESS(hive.used_free_slots, selected_caste)
if(used_slots)
hive.used_free_slots[selected_caste]--
var/new_val = LAZYACCESS(hive.free_slots, selected_caste) + 1
LAZYSET(hive.free_slots, selected_caste, new_val)

hive.remove_xeno(src)
hive?.remove_xeno(src)
remove_from_all_mob_huds()

observed_xeno = null
Expand Down
47 changes: 27 additions & 20 deletions code/modules/mob/living/carbon/xenomorph/xeno_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@
/datum/caste_datum/hivelord = 1,
/datum/caste_datum/carrier = 1
)
/// Assoc list of free slots currently used by specific castes
var/list/used_free_slots
/// Assoc list of slots currently used by specific castes (for calculating free_slot usage)
var/list/used_slots = list()
/// list of living tier2 xenos
var/list/tier_2_xenos = list()
/// list of living tier3 xenos
Expand Down Expand Up @@ -479,6 +479,12 @@
else if(xeno.tier == 3)
tier_3_xenos -= xeno

// Only handle free slots if the xeno is not in tdome
if(!is_admin_level(xeno.z))
var/selected_caste = GLOB.xeno_datum_list[xeno.caste_type]?.type
if(used_slots[selected_caste])
used_slots[selected_caste]--

if(!light_mode)
hive_ui.update_xeno_counts()
hive_ui.xeno_removed(xeno)
Expand Down Expand Up @@ -789,30 +795,31 @@
),
)

var/burrowed_factor = min(stored_larva, sqrt(4*stored_larva))
burrowed_factor = round(burrowed_factor)

var/used_tier_2_slots = length(tier_2_xenos)
var/used_tier_3_slots = length(tier_3_xenos)
for(var/caste_path in used_free_slots)
var/used_count = used_free_slots[caste_path]
if(!used_count)
continue
var/datum/caste_datum/C = caste_path
switch(initial(C.tier))
if(2) used_tier_2_slots -= used_count
if(3) used_tier_3_slots -= used_count

for(var/caste_path in free_slots)
var/slot_count = free_slots[caste_path]
if(!slot_count)
var/slots_free = free_slots[caste_path]
var/slots_used = used_slots[caste_path]
var/datum/caste_datum/current_caste = caste_path
if(slots_used)
// Don't count any free slots in use
switch(initial(current_caste.tier))
if(2)
used_tier_2_slots -= min(slots_used, slots_free)
if(3)
used_tier_3_slots -= min(slots_used, slots_free)
if(slots_free <= slots_used)
continue
var/datum/caste_datum/C = caste_path
switch(initial(C.tier))
if(2) slots[TIER_2][GUARANTEED_SLOTS][initial(C.caste_type)] = slot_count
if(3) slots[TIER_3][GUARANTEED_SLOTS][initial(C.caste_type)] = slot_count
// Display any free slots available
switch(initial(current_caste.tier))
if(2)
slots[TIER_2][GUARANTEED_SLOTS][initial(current_caste.caste_type)] = slots_free - slots_used
if(3)
slots[TIER_3][GUARANTEED_SLOTS][initial(current_caste.caste_type)] = slots_free - slots_used

var/effective_total = burrowed_factor
var/burrowed_factor = min(stored_larva, sqrt(4*stored_larva))
var/effective_total = round(burrowed_factor)
for(var/mob/living/carbon/xenomorph/xeno as anything in totalXenos)
if(xeno.counts_for_slots)
effective_total++
Expand Down

0 comments on commit b7ec827

Please sign in to comment.