Author Topic: Build Queue Exploit  (Read 3341 times)

0 Members and 1 Guest are viewing this topic.

Offline Petek

Build Queue Exploit
« on: April 12, 2013, 12:15:10 PM »
Here's another build queue exploit that hasn't been patched. Assume that you have Doc:AP and one of the techs that allows you to build a satellite. Have the base begin to build an Aerospace Complex (AC) and place a satellite in the build queue. Now replace the AC with something else. The satellite remains in the queue and will be built, even though the prerequisite AC isn't present. You can use the same technique in other situations. For example, build a Hybrid Forest without having a Tree Farm.

Online Buster's Uncle

  • In Buster's Orbit, I
  • Ascend
  • *
  • Posts: 49272
  • €442
  • View Inventory
  • Send /Gift
  • Because there are times when people just need a cute puppy  Soft kitty, warm kitty, little ball of fur  A WONDERFUL concept, Unity - & a 1-way trip that cost 400 trillion & 40 yrs.  
  • AC2 is my instrument, my heart, as I play my song.
  • Planet tales writer Smilie Artist Custom Faction Modder AC2 Wiki contributor Downloads Contributor
    • View Profile
    • My Custom Factions
    • Awards
Re: Build Queue Exploit
« Reply #1 on: April 12, 2013, 01:57:36 PM »
I can confirm this.

Offline scient

Re: Build Queue Exploit
« Reply #2 on: April 15, 2013, 04:12:49 PM »
There are a few instances of this.  If you put the first one in the production slot or in the queue, you can then put the follow up facility in some later queue slot.  If you remove the prerequisite, you can still build the follow up.

PERIMETER_DEFENSE  -> TACHYON_FIELD
RECREATION_COMMONS -> HOLOGRAM_THEATRE
TREE_FARM -> HYBRID_FOREST
FUSION_LAB -> QUANTUM_LAB
RESEARCH_HOSPITAL -> NANOHOSPITAL
HABITATION_DOME -> HAB_COMPLEX
ROBOTIC_ASSEMBLY_PLANT or GENEJACK_FACTORY -> NANOREPLICATOR
ROBOTIC_ASSEMBLY_PLANT -> QUANTUM_CONVERTER
CENTAURI_PRESERVE -> TEMPLE_OF_PLANET
AEROSPACE_COMPLEX  -> GEOSYNC_SURVEY_POD ; SKY_HYDRO_LAB ; NESSUS_MINING_STATION ; ORBITAL_POWER_TRANS ; ORBITAL_DEFENSE_POD

I noticed in the datalinks there isn't any reference to the prerequisite for "Tachyon Field", "Quantum Lab", "Geo Survey Pods", ODP, or "Quantum Converter".  Also, there isn't any mention that "Genejack Factory" can be a prerequisite for "Nanoreplicator".

You can also build "Paradise Garden" AND "Punishment Sphere" if you start by building "Punishment Sphere" and then put "Paradise Garden" into the queue.  Doesn't work the other way around but exploit does due to poor logic.

All this can be fixed with function that handles queue preq when you change production or delete something from queue.  Will look into it.

edit:
One other place it needs to be checked, when you scrap and recycle building facilities.


Offline scient

Re: Build Queue Exploit
« Reply #3 on: April 15, 2013, 08:27:43 PM »
So much redundant code in the function that loads production/queue facility list.  It looks like later in development they started to using one of existing function (or created one) to check whether base facility is present or in queue.  However with some of earlier facilities (7/10 of above), it is pretty much copy and paste of same loop check as external function to check this.  This leads to a MASSIVE amount of extra code.  On my first pass, I shrunk function size by 35% or ~750 bytes.  I can prob get it down even further once I do second pass restructuring function.

The shrink doesn't affect the game logic in any way other than I fixed the bug where you could build Punishment and Paradise at the same time.  Doing this rewrite will be very useful since code is exactly what will be used to prevent original exploit with rest of facilities.

Offline scient

Re: Build Queue Exploit
« Reply #4 on: April 23, 2013, 06:13:38 PM »
I gave up trying to rewrite this in asm since there are so many jumps and shifting them is a pain.  I ended up decompiling the function completely along with any sub functions and some of game structures.  Well, except the check if ocean is in radius because I need to do some more analysis on map structure.  I did optimize the code slightly in sense I used BASE_has_facility_ex() and BASE_has_secret_project() in places where it was copy and paste of function code.  This is why it was so bloated.  But the logic is the same, including the two bugs I marked.  Solving the bug in original post should be a simple loop to BASE_load_production_queue_list() when queue or production slot changes.

Here is code if anyone is interested in looking at some of internals.  I need to go over it a few more times, then it's just a matter of fixing up a few offsets so it works in existing code.

Code: [Select]
#define MAX_FACILITY_NUM 133
#define MAX_TECHNOLOGY_NUM 89
#define MAX_FACT_NUM 8
#define MAX_SP_NUM 64
#define MAX_BASE_NUM 2048

class SMACX_CORE {

public:
enum game_diff_level {
DIFF_CITIZEN,
DIFF_SPECIALIST,
DIFF_TALENT,
DIFF_LIBRARIAN,
DIFF_THINKER,
DIFF_TRANSCEND
};

enum game_rules_2 : DWORD {
TECH_STAGNATION = 0x20,
INTENSE_RIVALRY = 0x40,
IRONMAN = 0x400,
VICTORY_HIGHER_GOAL = 0x800,
DISABLE_SP_PRODUCTION = 0x80000000,
};

enum faction_special_rules : DWORD {
FACT_TECHSTEAL   = 0x10,
FACT_TECHSHARE   = 0x20,
FACT_WORMPOLICE  = 0x40,
FACT_ALIEN       = 0x80,
FACT_AQUATIC     = 0x100,
FACT_FREEPROTO   = 0x200,
FACT_FANATIC     = 0x400,
FACT_MINDCONTROL  = 0x800,
FACT_COMMFREQ    = 0x1000,
FACT_TERRAFORM   = 0x2000,
FACT_INTEREST    = 0x4000,
FACT_MORALE      = 0x8000,
};
};

class BASE_Management {

public:
enum facility_id {
FACL_HEADQUARTERS  = 1,
FACL_CHILDREN_CRECHE  = 2,
FACL_RECYCLING_TANKS  = 3,
FACL_PERIMETER_DEFENSE  = 4,
FACL_TACHYON_FIELD  = 5,
FACL_RECREATION_COMMONS  = 6,
FACL_ENERGY_BANK  = 7,
FACL_NETWORK_NODE  = 8,
FACL_BIOLOGY_LAB  = 9,
FACL_SKUNKWORKS  = 10,
FACL_HOLOGRAM_THEATRE  = 11,
FACL_PARADISE_GARDEN  = 12,
FACL_TREE_FARM   = 13,
FACL_HYBRID_FOREST  = 14,
FACL_FUSION_LAB  = 15,
FACL_QUANTUM_LAB  = 16,
FACL_RESEARCH_HOSPITAL  = 17,
FACL_NANOHOSPITAL  = 18,
FACL_ROBOTIC_ASSEMBLY_PLANT  = 19,
FACL_NANOREPLICATOR  = 20,
FACL_QUANTUM_CONVERTER  = 21,
FACL_GENEJACK_FACTORY  = 22,
FACL_PUNISHMENT_SPHERE  = 23,
FACL_HAB_COMPLEX  = 24,
FACL_HABITATION_DOME  = 25,
FACL_PRESSURE_DOME  = 26,
FACL_COMMAND_CENTER  = 27,
FACL_NAVAL_YARD  = 28,
FACL_AEROSPACE_COMPLEX  = 29,
FACL_BIOENHANCEMENT_CENTER  = 30,
FACL_CENTAURI_PRESERVE  = 31,
FACL_TEMPLE_OF_PLANET  = 32,
FACL_PSI_GATE    = 33,
FACL_COVERT_OPS_CENTER  = 34,
FACL_BROOD_PIT   = 35,
FACL_AQUAFARM    = 36,
FACL_SUBSEA_TRUNKLINE  = 37,
FACL_THERMOCLINE_TRANSDUCER  = 38,
FACL_FLECHETTE_DEFENSE_SYS  = 39,
FACL_SUBSPACE_GENERATOR  = 40,
FACL_GEOSYNC_SURVEY_POD  = 41,
FACL_EMPTY_FACILITY_42  = 42,
FACL_EMPTY_FACILITY_64  = 64,
FACL_SKY_HYDRO_LAB  = 65,
FACL_NESSUS_MINING_STATION  = 66,
FACL_ORBITAL_POWER_TRANS  = 67,
FACL_ORBITAL_DEFENSE_POD  = 68,
FACL_STOCKPILE_ENERGY  = 69,
FACL_HUMAN_GENOME_PROJ  = 70,
FACL_COMMAND_NEXUS  = 71,
FACL_WEATHER_PARADIGM  = 72,
FACL_MERCHANT_EXCHANGE  = 73,
FACL_EMPATH_GUILD  = 74,
FACL_CITIZENS_DEFENSE_FORCE  = 75,
FACL_VIRTUAL_WORLD  = 76,
FACL_PLANETARY_TRANS_SYS  = 77,
FACL_XENOEMPATYH_DOME  = 78,
FACL_NEURAL_AMPLIFIER  = 79,
FACL_MARITIME_CONTROL_CENTER  = 80,
FACL_PLANETARY_DATALINKS  = 81,
FACL_SUPERCOLLIDER  = 82,
FACL_ASCETIC_VIRTUES  = 83,
FACL_LONGEVITY_VACCINE  = 84,
FACL_HUNTER_SEEKER_ALGO  = 85,
FACL_PHOLUS_MUTAGEN  = 86,
FACL_CYBORG_FACTORY  = 87,
FACL_THEORY_OF_EVERYTHING  = 88,
FACL_DREAM_TWISTER  = 89,
FACL_UNIVERSAL_TRANSLATOR  = 90,
FACL_NETWORK_BACKBONE  = 91,
FACL_NANO_FACTORY  = 92,
FACL_LIVING_REFINERY  = 93,
FACL_CLONING_VATS  = 94,
FACL_SELF_AWARE_COLONY  = 95,
FACL_CLINICAL_IMMORTALITY  = 96,
FACL_SPACE_ELEVATOR  = 97,
FACL_SINGULARITY_INDUCTOR  = 98,
FACL_BULK_MATTER_TRANSMITTER  = 99,
FACL_TELEPATHIC_MATRIX  = 100,
FACL_VOICE_OF_PLANET  = 101,
FACL_ASCENT_TO_TRANSCENDENCE  = 102,
FACL_MANIFOLD_HARMONICS  = 103,
FACL_NETHACK_TERMINUS  = 104,
FACL_CLOUDBASE_ACADEMY  = 105,
FACL_PLANETARY_ENERGY_GRID  = 106,
FACL_EMPTY_SP_38  = 107,
FACL_EMPTY_SP_64  = 133,
};

int BASE_load_production_queue_list(int facil_prod_id, int faction_id, int base_id, int queue_slot_id);
int BASE_main(int factionID);
};

struct facility_data_struct {
int FACL_struct_name_str; // LPSTR
int FACL_struct_effect_str; // LPSTR
int FACL_struct_unk; // unused, set to 0
int FACL_struct_cost;
int FACL_struct_maint;
int FACL_struct_preq_tech_id;
int FACL_struct_FREE; // disable, automatically set to -2
int FACL_struct_SP_AI_fight;
int FACL_struct_SP_AI_growth;
int FACL_struct_SP_AI_tech;
int FACL_struct_SP_AI_wealth;
int FACL_struct_SP_AI_power;
} facility_data[MAX_FACILITY_NUM];

struct technology_data_struct {
int TECH_struct_flags;
int TECH_struct_name_str; // LPSTR
CHAR TECH_id_str[8];
int TECH_struct_unk; // unused
int TECH_struct_growth;
int TECH_struct_tech;
int TECH_struct_wealth;
int TECH_struct_power;
int TECH_struct_preq_tech1;
int TECH_struct_preq_tech2;
} technology_data[MAX_TECHNOLOGY_NUM];

struct faction_data_struct {
int FACT_struct_gender;
CHAR FACT_struct_filename[24];
CHAR FACT_struct_search_key[24];
CHAR FACT_struct_leader_name[24];
CHAR FACT_struct_leader_title[24];
// cont
DWORD FACT_struct_spec_rules_bitfield;
} faction_data[MAX_FACT_NUM];

struct base_data_struct {
WORD base_struct_x_coord;
WORD base_struct_y_coord;
BYTE base_struct_faction_current;
BYTE base_struct_faction_former;
BYTE base_struct_population_size;
BYTE base_struct_assimilation_timer;
BYTE base_struct_nerve_staple_effect;
BYTE base_struct_unk1;
BYTE base_struct_unk2;
BYTE base_struct_faction_pop_size_intel[8];
CHAR base_struct_name_str[25];
WORD base_struct_unk_x_coord;
WORD base_struct_unk_y_coord;
DWORD base_struct_status_bitfield;
DWORD base_struct_events_bitfield2;
DWORD base_struct_unk3;
DWORD base_struct_unk4;
DWORD base_struct_unk5;
DWORD base_struct_unk6;
DWORD base_struct_unk7;
DWORD base_struct_queue_size;
DWORD base_struct_queue_id[10];
DWORD base_struct_unk8;
DWORD base_struct_unk9;
DWORD base_struct_unk10;
DWORD base_struct_unk11;
DWORD base_struct_unk12;
BYTE base_facilities_table[12];
// cont
} base_data[MAX_BASE_NUM];

// globals

int GVAR_DIFF_level = SMACX_CORE::DIFF_TRANSCEND;
int GVAR_game_rules_bitfield_2 = 0x00001A0E;
int GVAR_SMACX_TGL = 1;
CHAR GVAR_STR_TEMP[1024] = { 0 };

BYTE GVAR_GAME_TECH_DISCOVERED[MAX_TECHNOLOGY_NUM] = { 0 };
DWORD GVAR_GAME_SP_LOCATION[MAX_SP_NUM] = { -1 }; // init to not built

// functions

int BASE_has_secret_project(int spID, int factionID) {
int spBaseID = GVAR_GAME_SP_LOCATION[spID];
if(spBaseID >= 0)
return base_data[spBaseID].base_struct_faction_current == factionID;
return 0;
}

int BASE_facility_struct_offset(int facilID, int *facilOffset, int *facilBit) {
*facilOffset = facilID / 8;
int result = 1 << (facilID & 7);
*facilBit = result;
return result;
}

int BASE_has_facility_ex(int facilID, int baseID, int queueSlot)
{
if(facilID >= BASE_Management::FACL_SKY_HYDRO_LAB)
return 0;
int facilOffset, facilBit;
BASE_facility_struct_offset(facilID, &facilOffset, &facilBit);

int returnVal = facilBit & base_data[baseID].base_facilities_table[facilOffset];
if(returnVal || !queueSlot)
return returnVal;

if(queueSlot <= 0)
return 0;

for(int nPos = 0; nPos < queueSlot; nPos++) {
if(base_data[baseID].base_struct_queue_id[nPos] == -facilID)
return 1;
}

return 0;
}

int SQUARE_is_ocean_adjacent(int x_coord, int y_coord, int toggle) {
return 1;
}

int BASE_load_production_queue_list(int facilID, int factionID, int baseID, int queueSlot) {
if(!facilID)
return 0;

if(facilID == BASE_Management::FACL_SKUNKWORKS){
if(GVAR_DIFF_level <= SMACX_CORE::DIFF_SPECIALIST)
return 0;
}else{
if((facilID >= BASE_Management::FACL_HUMAN_GENOME_PROJ) && (GVAR_game_rules_bitfield_2 & SMACX_CORE::DISABLE_SP_PRODUCTION))
return 0;
if(facilID == BASE_Management::FACL_ASCENT_TO_TRANSCENDENCE){
if(GVAR_GAME_SP_LOCATION[BASE_Management::FACL_VOICE_OF_PLANET-BASE_Management::FACL_HUMAN_GENOME_PROJ] == -1)
return 0;
if(GVAR_game_rules_bitfield_2 & SMACX_CORE::VICTORY_HIGHER_GOAL)
return 1; // bug: can return TRUE as CARETAKERS
else
return 0;
}
}

if(factionID <= 0)
return 0;

int tech_preq = facility_data[factionID].FACL_struct_preq_tech_id;
if(tech_preq != -1){
if(tech_preq < 0 || tech_preq >= 88 || technology_data[tech_preq].TECH_struct_preq_tech1 < -1 ||
technology_data[tech_preq].TECH_struct_preq_tech2 < -1 || technology_data[tech_preq].TECH_struct_preq_tech1 == -1 ||
!((1 << factionID) & GVAR_GAME_TECH_DISCOVERED[tech_preq]))
return 0;
}

if(!GVAR_SMACX_TGL && (facilID == BASE_Management::FACL_MANIFOLD_HARMONICS || facilID == BASE_Management::FACL_NETHACK_TERMINUS
|| facilID == BASE_Management::FACL_CLOUDBASE_ACADEMY || facilID == BASE_Management::FACL_PLANETARY_ENERGY_GRID)
|| (GVAR_STR_TEMP[0] = 0, strcat(GVAR_STR_TEMP, faction_data[factionID].FACT_struct_filename), CharUpperA(GVAR_STR_TEMP), !strcmp(GVAR_STR_TEMP, "CARETAKE"))
&& (facilID == BASE_Management::FACL_VOICE_OF_PLANET || facilID == BASE_Management::FACL_ASCENT_TO_TRANSCENDENCE))
return 0;

if(facilID >=  BASE_Management::FACL_HUMAN_GENOME_PROJ)
return GVAR_GAME_SP_LOCATION[facilID-BASE_Management::FACL_HUMAN_GENOME_PROJ] == -1;

if(baseID < 0)
return 1;

if(BASE_has_facility_ex(facilID, baseID, queueSlot))
return 0;

if(facilID == BASE_Management::FACL_NAVAL_YARD){
int MMC_baseID = GVAR_GAME_SP_LOCATION[BASE_Management::FACL_MARITIME_CONTROL_CENTER-BASE_Management::FACL_HUMAN_GENOME_PROJ];
if(MMC_baseID >= 0 && base_data[MMC_baseID].base_struct_faction_current == factionID)
return 0;
if(!SQUARE_is_ocean_adjacent(base_data[baseID].base_struct_x_coord, base_data[baseID].base_struct_y_coord, 0))
return 0;
}else{
int spID;
if(facilID == BASE_Management::FACL_PERIMETER_DEFENSE){
spID = BASE_Management::FACL_CITIZENS_DEFENSE_FORCE-BASE_Management::FACL_HUMAN_GENOME_PROJ;
goto CHECK_SP;
}else if(facilID == BASE_Management::FACL_COMMAND_CENTER){
spID = BASE_Management::FACL_COMMAND_NEXUS-BASE_Management::FACL_HUMAN_GENOME_PROJ;
goto CHECK_SP;
}else if(facilID == BASE_Management::FACL_BIOENHANCEMENT_CENTER){
spID = BASE_Management::FACL_CYBORG_FACTORY-BASE_Management::FACL_HUMAN_GENOME_PROJ;
goto CHECK_SP;
}else if(facilID == BASE_Management::FACL_QUANTUM_CONVERTER){
spID = BASE_Management::FACL_SINGULARITY_INDUCTOR-BASE_Management::FACL_HUMAN_GENOME_PROJ;
goto CHECK_SP;
}else if(facilID == BASE_Management::FACL_AEROSPACE_COMPLEX){
spID = BASE_Management::FACL_CLOUDBASE_ACADEMY-BASE_Management::FACL_HUMAN_GENOME_PROJ;
goto CHECK_SP;
}else if(facilID == BASE_Management::FACL_ENERGY_BANK){
spID = BASE_Management::FACL_PLANETARY_ENERGY_GRID-BASE_Management::FACL_HUMAN_GENOME_PROJ;
CHECK_SP:
if(BASE_has_secret_project(spID, factionID))
return 0;
}else if((facilID == BASE_Management::FACL_AQUAFARM || facilID == BASE_Management::FACL_SUBSEA_TRUNKLINE || facilID == BASE_Management::FACL_THERMOCLINE_TRANSDUCER)
&& (!GVAR_SMACX_TGL || !SQUARE_is_ocean_adjacent(base_data[baseID].base_struct_x_coord, base_data[baseID].base_struct_y_coord, 0)))
return 0;
}

if(!GVAR_SMACX_TGL && (facilID == BASE_Management::FACL_GEOSYNC_SURVEY_POD || facilID == BASE_Management::FACL_COVERT_OPS_CENTER
|| facilID == BASE_Management::FACL_BROOD_PIT || facilID == BASE_Management::FACL_FLECHETTE_DEFENSE_SYS || facilID == BASE_Management::FACL_SUBSPACE_GENERATOR)
|| !(faction_data[factionID].FACT_struct_spec_rules_bitfield & SMACX_CORE::FACT_ALIEN) && facilID == BASE_Management::FACL_SUBSPACE_GENERATOR)
return 0;

if(facilID == BASE_Management::FACL_RECYCLING_TANKS){
if(BASE_has_facility_ex(BASE_Management::FACL_PRESSURE_DOME, baseID, queueSlot))
return 0;
return 1;
}

if(facilID == BASE_Management::FACL_TACHYON_FIELD){
if(BASE_has_facility_ex(BASE_Management::FACL_PERIMETER_DEFENSE, baseID, queueSlot))
return 1;
if(BASE_has_secret_project(BASE_Management::FACL_CITIZENS_DEFENSE_FORCE-BASE_Management::FACL_HUMAN_GENOME_PROJ, factionID))
return 1;
return 0;
}

if(facilID == BASE_Management::FACL_HOLOGRAM_THEATRE){
if(!BASE_has_facility_ex(BASE_Management::FACL_RECREATION_COMMONS, baseID, queueSlot))
return 0;
if(BASE_has_secret_project(BASE_Management::FACL_VIRTUAL_WORLD-BASE_Management::FACL_HUMAN_GENOME_PROJ, factionID))
return 0;
return 1;
}

if(facilID == BASE_Management::FACL_HYBRID_FOREST){
if(BASE_has_facility_ex(BASE_Management::FACL_TREE_FARM, baseID, queueSlot))
return 1;
return 0;
}

if(facilID == BASE_Management::FACL_QUANTUM_LAB){
if(BASE_has_facility_ex(BASE_Management::FACL_FUSION_LAB, baseID, queueSlot))
return 1;
return 0;
}

if(facilID == BASE_Management::FACL_NANOHOSPITAL){
if(BASE_has_facility_ex(BASE_Management::FACL_RESEARCH_HOSPITAL, baseID, queueSlot))
return 1;
return 0;
}

if(facilID == BASE_Management::FACL_SKUNKWORKS) {
if(faction_data[factionID].FACT_struct_spec_rules_bitfield & SMACX_CORE::FACT_FREEPROTO)
return 0;
return 1;
}

if(facilID == BASE_Management::FACL_PUNISHMENT_SPHERE){
if(BASE_has_facility_ex(BASE_Management::FACL_PARADISE_GARDEN, baseID, queueSlot))
return 0;
return 1;
}

// bug: missing check to disable FACL_PARADISE_GARDEN if FACL_PUNISHMENT_SPHERE is being built

if(facilID == BASE_Management::FACL_HABITATION_DOME){
if(BASE_has_facility_ex(BASE_Management::FACL_HAB_COMPLEX, baseID, queueSlot))
return 1;
return 0;
}

if(facilID >= BASE_Management::FACL_SKY_HYDRO_LAB && facilID < BASE_Management::FACL_STOCKPILE_ENERGY ||
facilID == BASE_Management::FACL_GEOSYNC_SURVEY_POD){
if(BASE_has_facility_ex(BASE_Management::FACL_AEROSPACE_COMPLEX, baseID, queueSlot))
return 1;
if(BASE_has_secret_project(BASE_Management::FACL_CLOUDBASE_ACADEMY-BASE_Management::FACL_HUMAN_GENOME_PROJ, factionID))
return 1;
if(BASE_has_secret_project(BASE_Management::FACL_SPACE_ELEVATOR-BASE_Management::FACL_HUMAN_GENOME_PROJ, factionID))
return 1;
return 0;
}

if(facilID == BASE_Management::FACL_NANOREPLICATOR) {
if(BASE_has_facility_ex(BASE_Management::FACL_ROBOTIC_ASSEMBLY_PLANT, baseID, queueSlot))
return 1;
if(BASE_has_facility_ex(BASE_Management::FACL_GENEJACK_FACTORY, baseID, queueSlot))
return 1;
return 0;
}

if(facilID == BASE_Management::FACL_QUANTUM_CONVERTER) {
if(BASE_has_facility_ex(BASE_Management::FACL_ROBOTIC_ASSEMBLY_PLANT, baseID, queueSlot))
return 1;
return 0;
}

if(facilID == BASE_Management::FACL_TEMPLE_OF_PLANET) {
if(BASE_has_facility_ex(BASE_Management::FACL_CENTAURI_PRESERVE, baseID, queueSlot))
return 1;
return 0;
}

return 1;
}

Offline Yitzi

Re: Build Queue Exploit
« Reply #5 on: April 23, 2013, 06:51:39 PM »
Ooh, you found Intense Rivalry.  That'll be useful for setting up a different difficulty level for AI aggressiveness (for a more builder-ish game on Transcend.)

Offline scient

Re: Build Queue Exploit
« Reply #6 on: October 24, 2019, 05:10:26 AM »
Talk about coming full circle. I just finished redoing this function from scratch (BASE_load_production_queue_list is actually facility_avail), noticed the inconsistent with Punishment Sphere and Paradise Garden, started to make a post about it, figured I should probably search first, only to come across my own post from 6+ years ago. Didn't even remember decompiling this function to begin with. :doh

At least the code base for OpenSMACX is 1000% better and I likely would have done it from scratch anyway. I've put in a fix for PS/PG along with Ascent to Transcendence for Caretakers. Going to review my new code for any other inconsistencies I might have missed before. The exploit Petek describes in OP would be fixed in a different function likely ProdPicker::calculate(). I'm guessing it just needs an additional validation check to existing queue items once something is replaced or deleted. I've added this to my notes to review in future.


Offline scient

Re: Build Queue Exploit
« Reply #7 on: October 25, 2019, 07:14:49 PM »
I finished testing / checking for regression. As part of this, I went through the manual and official strategy guide to review all facilities and secret projects. Everything looks good and matches up as expected with logic (prerequisites, necessary conditions, supersedence) except for the already documented issue with Caretakers/Ascent and PG/PS. In some cases, the manual references "cumulative" which translates to needing a prerequisite.

The only one that didn't have clear documentation that I could find is Hologram Theater requiring Recreation Commons. However, that progression kind of makes sense and is pretty clearly intended in code. One thing I did notice is that it prevents you from constructing  Hologram Theaters if the faction has Virtual World even if you don't already have a Network Node in base. I don't think there is a reason you would pick a Hologram Theater over Network Node if you had Virtual World.

Offline bvanevery

  • Emperor of the Tanks
  • Thinker
  • *
  • Posts: 6370
  • €659
  • View Inventory
  • Send /Gift
  • Allows access to AC2's quiz & chess sections for 144 hours from time of use.  You can't do without Leadship  Must. have. caffeine. -Ahhhhh; good.  Premium environmentally-responsible coffee, grown with love and care by Gaian experts.  
  • Planning for the next 20 years of SMACX.
  • AC2 Hall Of Fame AC Text modder Author of at least one AAR
    • View Profile
    • Awards
Re: Build Queue Exploit
« Reply #8 on: December 15, 2019, 05:03:47 AM »
I don't think there is a reason you would pick a Hologram Theater over Network Node if you had Virtual World.

Only if your opponent had the Network Backbone in a highly tech producing place, i.e. their super capitol, and you were obsessed with not contributing to their research in any way at all.

Only if you were worried about your opponent conquering your base soon, and not wanting them to have somewhere to cash an Artifact they have nearby.

You really have to contort to come up with circumstances where it could sorta matter.

Offline scient

Re: Build Queue Exploit
« Reply #9 on: December 15, 2019, 10:26:52 PM »
I don't think there is a reason you would pick a Hologram Theater over Network Node if you had Virtual World.

Only if your opponent had the Network Backbone in a highly tech producing place, i.e. their super capitol, and you were obsessed with not contributing to their research in any way at all.

Only if you were worried about your opponent conquering your base soon, and not wanting them to have somewhere to cash an Artifact they have nearby.

You really have to contort to come up with circumstances where it could sorta matter.

I agree, there probably are some edge cases but I'm going to leave Hologram Theater / NN logic as is with my minimal touch mindset. Someone is always welcome to make mods in future. :)

Online Buster's Uncle

  • In Buster's Orbit, I
  • Ascend
  • *
  • Posts: 49272
  • €442
  • View Inventory
  • Send /Gift
  • Because there are times when people just need a cute puppy  Soft kitty, warm kitty, little ball of fur  A WONDERFUL concept, Unity - & a 1-way trip that cost 400 trillion & 40 yrs.  
  • AC2 is my instrument, my heart, as I play my song.
  • Planet tales writer Smilie Artist Custom Faction Modder AC2 Wiki contributor Downloads Contributor
    • View Profile
    • My Custom Factions
    • Awards
Re: Build Queue Exploit
« Reply #10 on: April 11, 2022, 03:02:38 AM »
bump

 

* User

Welcome, Guest. Please login or register.
Did you miss your activation email?


Login with username, password and session length

Select language:

* Community poll

SMAC v.4 SMAX v.2 (or previous versions)
-=-
24 (7%)
XP Compatibility patch
-=-
9 (2%)
Gog version for Windows
-=-
103 (32%)
Scient (unofficial) patch
-=-
40 (12%)
Kyrub's latest patch
-=-
14 (4%)
Yitzi's latest patch
-=-
89 (28%)
AC for Mac
-=-
3 (0%)
AC for Linux
-=-
6 (1%)
Gog version for Mac
-=-
10 (3%)
No patch
-=-
16 (5%)
Total Members Voted: 314
AC2 Wiki Logo
-click pic for wik-

* Random quote

Until quite recently, spider silk had the highest tensile strength of any substance known to man, and the name silksteel pays homage to the arachnid for good reason.
~Commissioner Pravin Lal 'U.N. Scientific Survey'

* Select your theme

*
Templates: 5: index (default), PortaMx/Mainindex (default), PortaMx/Frames (default), Display (default), GenericControls (default).
Sub templates: 8: init, html_above, body_above, portamx_above, main, portamx_below, body_below, html_below.
Language files: 4: index+Modifications.english (default), TopicRating/.english (default), PortaMx/PortaMx.english (default), OharaYTEmbed.english (default).
Style sheets: 0: .
Files included: 45 - 1228KB. (show)
Queries used: 40.

[Show Queries]