bokauk Posted October 24, 2012 Share Posted October 24, 2012 if you set a cost to build the pistols, granades, kevlar etc, instead of free (unlimited) would that remove the problem of generating cash for free? (selling unlimited items) would also add the element of potential military bankrupcy cos u cannot get arms for free anymore. and forcing you to turn down missions due to lack of weaponry. Yea, that's an idea, I might look into it. It'd be a bit more true to the original Xcom, from what I remember :) I think there are many other variables and game mechanics that influence balancing problems in the game, so I wouldn't expect that just being able to sell some unwanted items, would disrupt that hugely. I might be wrong, but if it does significantly skew the balance, then turning up the difficulty is an option :) Link to comment Share on other sites More sharing options...
Daemonjax Posted October 24, 2012 Share Posted October 24, 2012 (edited) All the starter equipment has a cost of -1, so that is not a problem. The last return statement returns false for all items with a iCash of -1. That's solved. Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000040 C8 35 00 00 4A 16 07 8C 00 84 84 9A 35 B7 02 00 È5..J..Œ.„„š5·.. Changing the 0x07 at offset 0x46 to 0x06 should just skip the first conditional, while leaving everything else alone. Yeah... function bool CanBeSold(int iItem) { local TItem kItem; kItem = Item(iItem); // This is an implied JumpToken; goto J0x8c; // kItem.iCategory == 1 || (kItem.iCategory == 2) || (kItem.iCategory == 3); // return false; J0x8c: // End:0xd4 Loop:False if(iItem == 192 || (iItem == 135) || (iItem == 133) || (iItem == 134)) { return false; } return m_arrItems[iItem].iCash != -1; } It'll skip the code I commented out. The problem is with items like interceptors and SHIVs -- things that have positive iCash values, but require no materials (alloys, elerium, corpses, etc) to make. Edited October 24, 2012 by Daemonjax Link to comment Share on other sites More sharing options...
rb0k Posted October 25, 2012 Share Posted October 25, 2012 The problem is with items like interceptors and SHIVs -- things that have positive iCash values, but require no materials (alloys, elerium, corpses, etc) to make. I was planning on converting if(kItem.iCategory == 1 || (kItem.iCategory == 2) || (kItem.iCategory == 3)) into if (kItem.iCategory < 4 && (kItem.iElerium == -1)) If my guess is right that would prohibit the sale of the following... eItem_BEGIN_WEAPONS,eItem_Pistol,eItem_AssaultRifle,eItem_Shotgun,eItem_LMG,eItem_SniperRifle,eItem_RocketLauncher,eItem_END_WEAPONS,eItem_BEGIN_ARMOR,eItem_ArmorKevlar,eItem_END_ITEMS,eItem_BEGIN_GRENADES,eItem_FragGrenade,eItem_SmokeGrenade,eItem_FlashBang,eItem_AlienGrenade,eItem_BattleScanner,eItem_END_GRENADES,eItem_BEGIN_VEHICLES,eItem_SHIV,eItem_SHIV_Alloy,eItem_SHIV_Hover,eItem_Interceptor,eItem_Skyranger,eItem_Satellite,eItem_BEGIN_VEHICLE_UPGRADES,eItem_ShivMinigun,eItem_ShivSentry,eItem_ShivLaser,eItem_ShivPlasma,eItem_SHIVDeck_I,eItem_SHIVDeck_II,eItem_SHIVDeck_III,eItem_IntWeap_I,eItem_IntWeap_II, Alien grenade (88) is the only one in that list I would consider sell-able. Maybe I can use the third condition for that. Link to comment Share on other sites More sharing options...
bokauk Posted October 25, 2012 Share Posted October 25, 2012 (edited) I was planning on converting if(kItem.iCategory == 1 || (kItem.iCategory == 2) || (kItem.iCategory == 3)) into if (kItem.iCategory < 4 && (kItem.iElerium == -1)) Let us know how you get on with the bytecode for that. I'd be very impressed if you got it to work and I'd love to be able to make more than just simple manipulations such as changing ints and operators etc :) Any idea how you would specify which variable in bytecode (eg, kItem.iElerium)? I know 00 is local variable, but in some cases, how do you specify which one? I imagine it becomes even more complicated when trying to reference a variable that isn't local, which you'll be doing. Edited October 25, 2012 by bokauk Link to comment Share on other sites More sharing options...
rb0k Posted October 26, 2012 Share Posted October 26, 2012 Well, I'm getting closer, but these jumps are killing me. This is the new output from UE Explorer. Haven't even tried running it. function bool CanBeSold(int iItem) { local TItem kItem; kItem = Item(iItem); // End:0x8c Loop:False if(kItem.iCategory < 4 && kItem.iElerium == -1) { return false; // End:0xd4 Loop:False if(iItem == 192 || (iItem == 135) || (iItem == 133) || (iItem == 134)) { } return false; return m_arrItems[iItem].iCash != -1; } return ReturnValue; @NULL(131072) } I've tried padding the unused space with EX_Nothing(0x0B) and I've tried just removing the unused space. Tomorrow, I'll play around with the jump values and see if something makes sense. Link to comment Share on other sites More sharing options...
Drakous79 Posted December 13, 2012 Share Posted December 13, 2012 (edited) Bump :) Wall of text incoming, you've been warned! I've managed to change CanBeSold function to give us more control of what can be sold. There are now 2 intervals instead of 4 items. The game did not crashed, while selling. Important notes at the start:If UE Explorer shows the function name in red color, there's some error and the game crashes.Also I've verified every jump by adding 26 to the end of IF statement and 0B-ing up to 04 3A D9 35 00 00 53. Next I increased jump's offest by one to see, if it would include 1 (26) I added.The Interval was not working, when I set it to allow some armors and return true in conjuction with kItem.iCategory == 2 and return false. Seems like kItem sets it hard.Needs testing. There is a bug, when freshly manufactured item did not appear in a list of sellable items. Happened after I loaded saved game, build something and went to grey market to check, if it's there. I had to sell something to get updated list.Big thanks to EliotVU for UE Explorer! XComStrategyGame.upk, class XGItemTree - ORIGINALfunction bool CanBeSold(int iItem) { local TItem kItem; kItem = Item(iItem); // End:0x8c if(kItem.iCategory == 1 || kItem.iCategory == 2 || kItem.iCategory == 3) { return false; } // End:0xd4 if(iItem == 192 || iItem == 135 || iItem == 133 || iItem == 134) { return false; } return m_arrItems[iItem].iCash != -1; }ALTEREDfunction bool CanBeSold(int iItem) { local TItem kItem; kItem = Item(iItem); // Cannot sell items in category 3 - Vehicles, Vehicle Weapons and Consumables, Satellites // iCategory < 0 and iCategory == 4 are just placeholders. Can be used for iElerium, iAlloy or to prohibit selling of armors (iCategory == 2). // End:0x8c if(kItem.iCategory < 0 || kItem.iCategory == 3 || kItem.iCategory == 4) { return false; } // Cannot sell Plasma Pistol, Light Plasma Rifle, Plasma Rifle, Alloy Cannon, Heavy Plasma, Plasma Sniper Rifle, Blaster Launcher. // Can sell any laser weapon. // End:0xb0 if(iItem >= 13 && iItem <= 19) { return false; } // Cannot sell Combat Stims, Mind Shield, Chitin Plating, Arc Thrower. // Can sell Medikit, S.C.O.P.E. and Nano-fiber Vest. // End:0xd4 if(iItem >= 77 && iItem <= 80) { return false; } return m_arrItems[iItem].iCash != -1; }SF: 07 8C 00 84 84 9A 35 B9 02 00 00 C8 02 00 00 00 00 00 D8 35 00 00 26 16 18 21 00 9A 35 B9 02 00 00 C8 02 00 00 00 00 00 D8 35 00 00 2C 02 16 16 18 21 00 9A 35 B9 02 00 00 C8 02 00 00 00 00 00 D8 35 00 00 2C 03 16 16 04 28 07 D4 00 84 84 84 9A 00 DA 35 00 00 2C C0 16 18 0E 00 9A 00 DA 35 00 00 2C 87 16 16 18 0E 00 9A 00 DA 35 00 00 2C 85 16 16 18 0E 00 9A 00 DA 35 00 00 2C 86 16 16 04 28 04 9B 35 C4 02 00 00 C8 02 00 00 00 00 10 00 DA 35 00 00 01 63 35 00 00 1D FF FF FF FF 16 RW: 07 8C 00 84 84 96 35 B9 02 00 00 C8 02 00 00 00 00 00 D8 35 00 00 25 16 18 21 00 9A 35 B9 02 00 00 C8 02 00 00 00 00 00 D8 35 00 00 2C 03 16 16 18 21 00 9A 35 B9 02 00 00 C8 02 00 00 00 00 00 D8 35 00 00 2C 04 16 16 04 28 07 B0 00 82 99 00 DA 35 00 00 2C 0D 16 18 0E 00 98 00 DA 35 00 00 2C 13 16 16 04 28 07 D4 00 82 99 00 DA 35 00 00 2C 4D 16 18 0E 00 98 00 DA 35 00 00 2C 50 16 16 04 28 04 9B 35 C4 02 00 00 C8 02 00 00 00 00 10 00 DA 35 00 00 01 63 35 00 00 1D FF FF FF FF 16 I've checked other functions in the class and found, they're referring iCash with the same numbers as are used in CanBeSold function. There's no need to set variable type, because there's mostly 35 struct preceding them. In the struct is also defined C8 02 00 00 which EU Explorer points to XGStrategyActor.TItem. Here's a list:// C4 02 00 00 iCash // C3 02 00 00 iElerium // C2 02 00 00 iAlloy // B9 02 00 00 iCategoryMaybe they can be used with 01 - instance variable token outside the struct. Here is another list with values for xItem:D8 35 00 00 kItem DA 35 00 00 iItemOne thing I noticed. If I used kItem elsewhere with preceding 00, the game crashed. Quick note about jumps. Counted bytes of conditionals by selecting everything from the start (07 xx xx) to the end (04 xx), added the result to previous jump offset and increased by 4 until I got it right. Maybe Eliot can explain to us how the jump byte actually works (I'm looking at you, function CanBeSold).Figuring the offset was a nightmare and yet so simple. Basically the offset is in bytes but for every occurrence of an object index/pointer it counts as an additional 4 bytes, so 64bit basically.07 8C (140) 00 ... byte count 4A (74) ... 140 - 74 = 66 / 4 = 16 objects? Isn't it too many?07 B0 (176) 00 ... byte count 1C (28) ... B0 - 8C = 24 (36) ... 36 - 28 = 8 / 4 = 2 objects?07 D4 (212) 00 ... byte count C1 (28) ... D4 - B0 = 24 (36) ... 36 - 28 = 8 / 4 = 2 objects? I also took list of values from BuildItems() function Daemonjax posted on the first page and assigned names to values in conjuction with enum EItemType within XComGame.upk, class XGGameData.// Category 1 - Weapons 2 Pistol //iCash -1 3 Assault Rifle //iCash -1 4 Shotgun //iCash -1 5 LMG //iCash -1 6 Sniper Rifle //iCash -1 7 Rocket Launcher //iCash -1 85 Frag Grenade //iCash -1 86 Smoke Grenade //iCash -1 76 Medikit 88 Alien Grenade //iCash -1 80 Arc Thrower 99 Battle Scanner //iCash -1 81 S.C.O.P.E. 82 Nano-fiber Vest 79 Chitin Plating 77 Combat Stims 78 Mind Shield 192 Skeleton Key 8 Laser Pistol 9 Laser Rifle 10 Scatter Laser 12 Laser Sniper Rifle 11 Heavy Laser 13 Plasma Pistol 14 Light Plasma Rifle 15 Plasma Rifle 16 Alloy Cannon 17 Heavy Plasma 18 Plasma Sniper Rifle 19 Blaster Launcher // Category 2 - Armors 57 Kevlar Armor //iCash -1 58 Carapace Armor 59 Skeleton Armor 60 Titan Armor 61 Archangel Armor 62 Ghost Armor 63 Psi Armor // Category 3 - Vehicles / Vehicle Weapons and Consumables / Satellites 102 S.H.I.V. 103 Alloy S.H.I.V. 104 Hover S.H.I.V. 105 Interceptor 106 Firestorm 107 Skyranger //iCash -1 108 Satellite 113 S.H.I.V. Weapon Minigun //iCash -1 115 S.H.I.V. Weapon Laser //iCash -1 116 S.H.I.V. Weapon Plasma //iCash -1 117 S.H.I.V. Armor Deck_I // with Minigun //iCash -1 118 S.H.I.V. Armor SHIVDeck_II // with Laser //iCash -1 119 S.H.I.V. Armor SHIVDeck_III // with Plasma //iCash -1 123 Ship Weapon Phoenix Cannon 124 Ship Weapon Avalanche Missiles //iCash -1 125 Ship Weapon Laser Cannon 126 Ship Weapon Plasma Cannon 127 Ship Weapon EMP Cannon 128 Ship Weapon Fusion Lance 135 Uplink Targeting (Aim) 133 Defense Matrix (Dodge) 134 UFO Tracking (Boost) // Category 4 - Vehicle Upgrades // Category 5 - Collectibles / Alien Artefacts 171 Elerium 115 172 Alien Alloys 173 Weapon Fragment 191 Outsider Shard //iCash -1 179 UFO Power Source 177 UFO Flight Computer 175 Alien Food 174 Alien Entertainment 176 Alien Stasis Tank 178 Alien Surgery 188 Fusion Core 180 Hyperwave Beacon //iCash -1 189 Ethereal Device //iCash -1 186 Damaged UFO Power Source 184 Damaged UFO Flight Computer 182 Damaged Alien Food 181 Damaged Alien Entertainment 183 Damaged Alien Stasis Tank 185 Damaged Alien Surgery 187 Damaged Hyperwave Beacon // Category 6 - Corpses / Captives 144 Sectoid Corpse 146 Floater Corpse 148 Thin Man Corpse 149 Muton Corpse 154 Cryssalid Corpse 152 Cyberdisc Wreck 156 Sectopod Wreck 157 Drone Wreck 153 Ethereal Corpse 145 Sectoid Commander Corpse 151 Berserker Corpse 150 Muton Elite Corpse 147 Heavy Floater Corpse 160 Sectoid Captive //iCash -1 162 Floater Captive //iCash -1 164 Thin Man Captive //iCash -1 165 Muton Captive //iCash -1 168 Ethereal Captive //iCash -1 161 Sectoid Commander Captive //iCash -1 167 Berserker Captive //iCash -1 166 Muton Elite Captive //iCash -1 163 Heavy Floater Captive //iCash -1 // Category 7 - Facilities, // Category 8 - Staff Almost at the end! :) Here is my best, but not working attempt, where I had match of bytes. 0B cannot be used to padd remaining space. I've tried with strings and math operations, but always ended with extra return ReturnValue. Peeked into CanBeBuilt and compared the end, but to no avail. Also note how function name changed.final iterator function bool CanBeSold(int iItem) { local TItem kItem; kItem = Item(iItem); // End:0x68 if(kItem.iCategory == 2 || kItem.iCategory == 3) { return false; } // End:0x8c if(iItem >= 76 && iItem <= 82) { return false; } // End:0xb0 if(iItem >= 76 && iItem <= 82) { return false; } // End:0xd4 if(iItem >= 76 && iItem <= 82) { return false; } return m_arrItems[iItem].iCash > 0; return ReturnValue; }This is going to crash the game: 07 68 00 84 9A 35 B9 02 00 00 C8 02 00 00 00 00 00 D8 35 00 00 2C 02 16 18 21 00 9A 35 B9 02 00 00 C8 02 00 00 00 00 00 D8 35 00 00 2C 03 16 16 04 28 07 8C 00 82 99 00 DA 35 00 00 2C 4C 16 18 0E 00 98 00 DA 35 00 00 2C 52 16 16 04 28 07 B0 00 82 99 00 DA 35 00 00 2C 4C 16 18 0E 00 98 00 DA 35 00 00 2C 52 16 16 04 28 07 D4 00 82 99 00 DA 35 00 00 2C 4C 16 18 0E 00 98 00 DA 35 00 00 2C 52 16 16 04 28 04 97 35 C4 02 00 00 C8 02 00 00 00 00 10 00 DA 35 00 00 01 63 35 00 00 25 16That's it. Good luck! Edited December 13, 2012 by Drakous79 Link to comment Share on other sites More sharing options...
Drakous79 Posted December 13, 2012 Share Posted December 13, 2012 (edited) Oh, few more things. These have the same byte size, if you ever need more control. Like in function bool ItemIsWeapon(int iItem) for an example. if(iItem == 111 || iItem == 111 || iItem == 111 || iItem == 111) { return false; }if(iItem == 111 || iItem == 111) { return false; } if(iItem == 111 || iItem == 111) { return false; }if(iItem == 111) { return false; } if(iItem == 111) { return false; } if(iItem == 111) { return false; } if(iItem == 111) { return false; }if(iItem >= 111 && iItem <= 111) { return false; } if(iItem >= 111 && iItem <= 111) { return false; } Another thing I wanted to post was about creating the interval. if(iItem >= 77 && iItem <= 80) { return false; } 07 D4 00 82 99 00 DA 35 00 00 2C 4D 16 18 0E 00 98 00 DA 35 00 00 2C 50 16 16 04 28 // 07 If // D4 00 Where if ends // 82 && Logical and sign // 99 >= Is greater than or equal sign // 00 Local variable follows // DA 35 00 00 iItem // 2C Integer constant of one byte follows // 4D Number 77 // 16 End ... first condition has one 16, following conditions have two 16s // 18 0E 00 ... this is between two conditions, is 18 21 00 in struct kItem.iCategory, so I just used the one from iItem conditionals // 98 <= Is less than or equal sign // 00 Local variable follows // DA 35 00 00 iItem // 2C Integer constant of one byte follows // 50 Number 80 // 16 16 End // 04 Return // 28 False Edited December 13, 2012 by Drakous79 Link to comment Share on other sites More sharing options...
Recommended Posts