Jump to content

Daemonjax

Supporter
  • Posts

    267
  • Joined

  • Last visited

Everything posted by Daemonjax

  1. Honestly, I think 5 base health for rookies is fine for all difficulty levels. There's so many other ways to make the game harder, that decreasing health a point or two is just unnecessary.
  2. I'll give it a shot right now. UPDATE: Nope, it has no effect. :( Nice find! Too bad it doesn't recompress. So, as of right now (fingers crossed), the only thing holding us back is lack of a compression tool. I think this usually isn't an issue for modders for other games built on this engine, because all the other games can load uncompressed upk files. Explains why no one has made a compressor, anyways. So, XCOM is more mod unfriendly than Borderlands? That's just sad.
  3. Yeah, all my attempts at getting the game to work with a recompressed upk have been with an unmodified one.
  4. Hehe... yeah, you'd be wrong. But don't worry... if you haven't taken any math courses in the last decade, you're forgiven. ;) The sum of rolling multiple dice creates something closer to a normal distribution around the average as you add more and more dice. If you can visualize one die as a straight horizontal line, 2 die is a pyramid, and 3 begins to look more like a hill, then the picture should become more clear. Also, If you ever played AD&D tabletop, you should remember that rolling an 18 on 3d6 happened way less than rolling a 20 on a d20 for the same reason. But, you really wouldn't want a normal distribution around the average of a d100 die roll in this game... unless your chance to hit or be hit was always 50%. The floating target number is complicates matters, which is the to-hit roll in AD&D is just 1d20 and not 2d10. So, while I think what the OP wants is doable in theory, it's not a simple matter of rolling more dice.
  5. The engine might generate mipmaps on the fly.
  6. http://www.oberhumer.com/opensource/lzo/lzofaq.php LZO1X-999 !---------- algorithm category !--------- algorithm type !!!----- compression level (1-9, 99, 999) LZO1X-1(11) !---------- algorithm category !--------- algorithm type !------- compression level (1-9, 99, 999) !!---- memory level (memory requirements for compression) - lzo1x_decompress The 'standard' decompressor. Pretty fast - use this whenever possible. This decompressor expects valid compressed data. If the compressed data gets corrupted somehow (e.g. transmission via an erroneous channel, disk errors, ...) it will probably crash your application because absolutely no additional checks are done. Ahah! So that's why it crashes when the file isn't compressed. And I guess LZOP's compressor does something a little bit differently which also causes a crash. So, I think we should just use the code found here: http://www.oberhumer.com/opensource/lzo/ to write our own compressor. There are .NET and Ruby bindings for it. Any volunteers? If not, I'll do it in C. UPDATE: I started working on it. Making some progress. Might take me a while because I have to reverse engineer everything Gildor figured out. Right now I'm trying to work out how the upk file header is laid out. I found this thread, and it appears useful: http://www.gildor.org/smf/index.php/topic,297.msg2859.html These first 8 bytes do not change from one compressed upk to another: C1 83 2A 9E 00 00 02 00 UPDATE: This is harder than I thought it would be. I don't understand upk file structure enough to make this an easy coding assignment ;) Also, the size of the header seems to vary from file to file (except the first eight)... seen if your compare core.upk and engine.upk in a hexeditor. Maybe there's a reason no one's made a upk compressor.
  7. Try running it when the game isn't running, or ya messed the file up slightly when you made your changes. ;)
  8. You're welcome! ;) I downloaded and used LZOP. It gets close. Real close. I looked at the compressed and uncompressed versions of the file with using a hexeditor, and the entire UPK file is indeed compressed. If that's not the case, I'd be really surprised. I would try another program to compress it at this point, unfortunately none exist. So, we'd have to write one, and there's no guarantee it'd work with this engine in the end. UPDATE: Found a java implementation of the LZO algorithm. https://github.com/Karmasphere/lzo-java I'll give it a whirl. And, btw, the source code for the C version compiles no problem using just dev c++. I'm just OK with C, so if there's anyone else here that's awesome at it then that one's for you. :D UPDATE: Bad news. That code for Karmasphere is broken, and the author's email address just bounced back to me.
  9. I don't know for sure. I thought it would just decompress the file on the fly, doing whatever it needed to do. Having information tucked away in a compressed file that is usable before decompression sounds more complicated than it needs to be. I've never tried modding anything for the Unreal engine before... it's very very unfriendly. It's like I'm back in 1994... let's start breaking out the disassemblers and hexeditors. Anyways, LZOP does not compress it to the exact filesize. I wouldn't care, except that the game immediately crashes when trying to load with a recompressed file. \ Maybe that has something to do with what you're talking about. :D Working on it... UPDATE: Lzop does not recognize the original compressed file as being an lzop file. I'll have to whip out my hexeditor to see what's up. :/ Told ya. UPDATE2: I think I can fix the files compressed with LZOP to match what the engine is expecting. Working on it... While I'm at it, how about someone explain what these chunk infos are? UPDATE3: Close but no cigar. I can get it to crash a little later, that's all. By modifying the header... The game then complains in the log file about only finding like 100 classes out of 2000 in Core. Maybe it's not impossible, but I'm taking a break from looking at this for now. I'd rather just play the game, and this is starting to feel like work :P
  10. It's possible that it's SHA-0, not SHA-1. It's doesn't say SHA-1 in the output... it says SHA. I think it's unlikely that they used a salted or nonced hash value to protect the data... That'd mean they were REALLY serious about people not f***ing around with their files. ;) I think the hash check is there to guard against loading corrupted files, not for security reasons. Or... the UPK's could be compressed? I read somewhere that UPKs can exist in either compressed or uncompressed states. Maybe it's checking the hash value after uncompression? (Yeps, this was it!) Or... Our method of extraction changes the data in the UPK slightly. Even a 1 bit difference would totally change the hash value. (nevermind this one) Or... the output is a lie, and it's not SHA. It takes a while to generate the SHA hash value of a file, unless that file is very small. There's 2000+ upk files, and I highly doubt the game is generating SHA hash values for all of them in the time it takes the game to start (74 of them are over 10 megs). I could be wrong. I could write a program to test it. It's not an insignificant amount of time, though. Or... Perhaps... What program are you using to generate the SHA-1 hash? The value they're looking for may or may not be the retrieved hash after it's been converted to hex format. EDIT: Writing the program to test the time to generate SHA-1 hashes of all the upk files... I'll be back shortly :D import java.io.File; import java.io.FileInputStream; import java.security.MessageDigest; public class UPKHashCheck { public static void main(String[] args)throws Exception { File[] listOfFiles = new File("D:\\Program Files (x86)\\XCom-Enemy-Unknown\\XComGame\\CookedPCConsole").listFiles(); MessageDigest md = MessageDigest.getInstance("SHA"); int counter = 0; int j = 0; for (int i = listOfFiles.length - 1; i >= 0; --i) { if (listOfFiles[i].isFile()) { String file = listOfFiles[i].getName(); if (file.endsWith(".upk") || file.endsWith(".UPK")) { FileInputStream fis = new FileInputStream(listOfFiles[i]); byte[] dataBytes = new byte[1024]; int nread = 0; while ((nread = fis.read(dataBytes)) != -1) { md.update(dataBytes, 0, nread); } byte[] mdbytes = md.digest(); j += mdbytes[0]; ++counter; } } } counter += (j / Integer.MAX_VALUE); System.out.println(counter); } } Output: run: 2463 BUILD SUCCESSFUL (total time: 17 seconds) 17 seconds proves they are not checking SHA-1 hashes for all those files, so the only 3 options are: a) They're only checking some UPK files, but not others. b) It's not SHA-1 c) Java is ridiculously slow when it comes to generating file hashes If A is true, then they did it purely for security reasons and not for checking file corruption. Which is sad, because then it may be salted or nonced (it's also paranoid of them, imo). MD5 drops it to 12 seconds. Still too long for all the UPK files. UPDATE: Mistakenly used SHA-256. Fixed. ;) Can I see the expected hash for one of the files? Maybe I can figure it out. If they took the extra step to salt or nonce it, I think we're boned though. None of us are going to crack SHA anytime soon. ;) EDIT: Lol... just noticed the resource hacker comment. I guess there is a file list. :D I should have read your post more carefully, heh. Ok, I'll check the expected hash and see what I see. EDIT2: Ok, I'm making sense of it... still working on it, though. Here's the expected hash of core.upk to save someone else the time: 47 65 3C 8D B1 23 15 9F 22 AC C9 04 9F E0 55 B6 7A 4E 9E A2 Now, I'll write another program... import java.io.File; import java.io.FileInputStream; import java.security.MessageDigest; public class UPKHashVerify { public static void main(String[] args)throws Exception { MessageDigest md = MessageDigest.getInstance("SHA"); FileInputStream fis = new FileInputStream(new File("D:\\Program Files (x86)\\XCom-Enemy-Unknown\\XComGame\\CookedPCConsole\\core.upk")); byte[] dataBytes = new byte[1024]; int nread = 0; int[] expectedHash = {0x47, 0x65, 0x3C, 0x8D, 0xB1, 0x23, 0x15, 0x9F, 0x22, 0xAC, 0xC9, 0x04, 0x9F, 0xE0, 0x55, 0xB6, 0x7A, 0x4E, 0x9E, 0xA2}; while ((nread = fis.read(dataBytes)) != -1) { md.update(dataBytes, 0, nread); } fis.close(); byte[] mdbytes = md.digest(); System.out.println(md.getAlgorithm()); System.out.print("Expected: "); for (int i=0; i < expectedHash.length; ++i) { String hexString = Integer.toHexString(expectedHash[i]).toUpperCase(); if (hexString.length() == 1) hexString += "0"; System.out.print(hexString + " "); } System.out.print("\nActual..: "); for (int i = 0; i < mdbytes.length; ++i) { String hexString = Integer.toHexString((int)mdbytes[i] & 0xff).toUpperCase(); if (hexString.length() == 1) hexString += "0"; System.out.print(hexString + " "); } System.out.println(); } } Output: SHA Expected: 47 65 3C 8D B1 23 15 9F 22 AC C9 40 9F E0 55 B6 7A 4E 9E A2 Actual..: 10 F0 C0 CD 56 10 20 63 9B 51 E0 F5 48 6B 46 F5 A7 60 1A E7 Yeah, not good... let's look at the bits... UPDATE: Woops. I thought I figured it out, but I didn't. ;) Well, I have another idea... there may be a header of size X which the engine skips when doing the hash check. If that's true, I'll write a program that will find it. UPDATE: No, that's not it. I think I know what's going on... there's a file in the folder that gives a clue: Core.upk.uncompressed_size The contents of the file is simply: 223449 Since core.upk is 59k, then it must be compressed. So, I believe the game is most likely taking the hash of the uncompressed file. Using gildor's decompressor with the -lzo switch, I can decompress it to that filesize. (thanks, Gildor!) Running my program again to verify... and yeps... that did it: SHA Expected: 47 65 3C 8D B1 23 15 9F 22 AC C9 40 9F E0 55 B6 7A 4E 9E A2 Actual..: 47 65 3C 8D B1 23 15 9F 22 AC C9 40 9F E0 55 B6 7A 4E 9E A2 Solved, I guess. Only took me 5 hours of trying every wacky idea to find a solution that took 5 seconds to actually do. I'm such a noob! :D Can we unpack/repack/recompress yet? I think I found a way to recompress... The LZO compression the file uses is a good clue... give me a few minutes... Yeah, this should work... LZO is an obscure algorithm, but someone made a .net library for it. Here it is: http://lzo-net.sourceforge.net/ Someone else can do that part, because I don't feel like setting up a .NET programming environment on my PC. UPDATE: I might do it anyways, since I found some source code in C here: http://www.oberhumer.com/opensource/lzo/#download UPDATE: LZOP works right out of the box, so that saves us the trouble. http://www.lzop.org/ Testing lzop now...
  11. Can try grabbing names from babynaming help websites from various countries. They have male/female sections. Weird right? Parents going on the web to help name their kids... true story, tho. ;)
  12. WTF... Why is all this stuff intentionally packed away where it's a *censored* to get at? There must have been an option to let all these plaintext files be loose, but instead they chose to have them packed in upk files. Why??
  13. True enough about Europe, but I also wait till I get SA before I do any interrogations/autopsies. It's not a bonus to sneeze at. I don't agree about building any labs, due to Power constraints, but that's a different discussion. :D
  14. I think the devs should leak some modding tools for us to play with.
  15. Steam might complain if you alter the game's memory. Not sure, though.
  16. Make South America not suck (3 scientists and engineers with 2 satellites on easy/normal, 2 scientists and engineers on hard and impossible) South America doesn't suck, though. It's bonus is really good for when you're doing the sat rush strategy and have done next to no research and June rolls along. Here's default classic difficulty: iEngineers1=0, iScientists1=1, iEngineers2=1, iScientists2=1 ) So... you get 1 engineer and 2 scientists for grabbing SA in one month (which you should do, of course), and you changed it to 2/2... Ok, that's fair enough I suppose. :D
  17. This is the first game in a long long time where I never said to myself while playing, "Damn, that texture is terribad. I need to stop playing now and mod that." ;)
  18. Let me know when we can repack them. Till then... ::popcorn:: ;)
  19. I wouldn't rewrite Rand(), I'd just intercept the results before it got used. Then, determine If the roll sucked too much or was too good based on past results. Then, either carry on or reroll another random number. ;) If X past results were stored with the savegame, then the anti-savescumming feature would still work (which is hidden behind Rand() somewhere). EDIT: What dreadylein said. heh
  20. Yeah, I could see how a normalized RNG mod for this game would be popular. For example, in Path of Exile, the dodge stat is a random chance to dodge an attack... and it's normalized. So, if you have an exactly 50% chance to dodge, you'll never dodge twice in a row or not dodge twice in a row. Or something like that :D Look into however they did it, because it's done correctly in that game. Basically, the "dice" remembers past results to ensure you NEVER have streaks of good or bad luck. So, it's not random at all, but whatever. Most people don't want random. They see a shot for 50%, they take it, miss, and say to themselves: "Ok, I'll hit next time." It would be a challenge to make it work with the anti-savescumming feature, and also it would have to run some kind of statistical analysis of X # of past results since the chance to hit changes a lot from target to target. You may build it and realize it sucks for this type of game, but whatever. Just tune the X in "X # of past results" until it feels random enough. Instead of normalizing, then it would be more like anti-streaking measure. Like, if X was 8, then you could have a streak of good or bad luck for 8 rolls, but after that your luck would change for the better/worse. Wouldn't be luck, though, of course. heh
  21. You sure about this? Is it just a display bug? Haha, yeah, good point. I think we'll need to have random stat ranges for each class (with some overlap of course). A one size fits all approach will be frustrating, since too many stars would have to align to get a decent soldier. Or, maybe not... I'll have to try it and see. Might be fine, really... just the cost of hiring soldiers may need to be adjusted, since they'll probably suck. Also, the following is adjustable: LOW_AIM=50 HIGH_AIM=80 LOW_MOBILITY=12 HIGH_MOBILITY=14 LOW_WILL=20 HIGH_WILL=60 Low mobility should be 10, but otherwise the spread looks reasonable. In the OG buying 10 soldiers was pocket change, but in this game it's the cost of a workshop. Should probably halve the cost.. or not. Could be cool if money was tighter than it is in the midgame.
  22. Yeah, that's easy, just look in defaultgamecore.ini These should affects the ones your start with, as well as new hires: ROOKIE_AIM=65 ROOKIE_MOBILITY=12 ROOKIE_STARTING_WILL=40 If you want to adjust just the ones you start with, then look under the difficulty settings in the same file.
  23. That's a good idea, actually. Is gunslinger really OP though? Maybe, but only when compared to Snapshot... Any reductions to aim that aren't added to to the offense stat on rifles just makes Snapshot look even worse. To be honest, I actually increased the damage for laser and plasma pistols in my game by 1 (for the sectoids, too). I think both gunslinger and snapshot kinda suck, though. :D
×
×
  • Create New...