Complex If Statements menu

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    Amrok's Avatar Banned
    Reputation
    4
    Join Date
    Apr 2009
    Posts
    59
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Complex If Statements

    What do you think of my way to check if we got a playerBase (only read next pointer if previous pointer reading action was successful):

    ReadOffset returns NULL if it fails.

    Code:
    // read the playerBase
    UINT_PTR playerBase = Memory.ReadOffset<UINT_PTR>(Memory.BaseAddr+PlayerBasePointer);
    if (!(playerBase?playerBase=Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset1):false,playerBase?playerBase=Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset2):false))
    	Memory._error(7);
    else
    	std::cout << "The playerBase: " << reinterpret_cast<PVOID>(playerBase) << std::endl;
     .
    And this is how it would look like with normal if clauses:

    Code:
    // read the playerBase
    UINT_PTR playerBase = Memory.ReadOffset<UINT_PTR>(Memory.BaseAddr+PlayerBasePointer);
    if (playerBase != NULL)
    {
    	playerBase = Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset1);
    	if (playerBase != NULL)
    		playerBase = Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset2);
    }
    
    if (playerBase == NULL)
    	Memory._error(7);
    else
    	std::cout << "The playerBase: " << reinterpret_cast<PVOID>(playerBase) << std::endl;
    Which way would you prefer?
    Last edited by Amrok; 08-15-2011 at 12:25 PM.

    Complex If Statements
  2. #2
    flo8464's Avatar Active Member
    Reputation
    30
    Join Date
    Apr 2009
    Posts
    434
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I already read and wrote tons of C++ Code and I really have problems to understand what the heck you are doing in your first snippet.
    I even think it's wrong as it's doesn't seem to be logically aequivalent to your second solution, which is much better by the way.
    Hey, it compiles! Ship it!

  3. #3
    schlumpf's Avatar Retired Noggit Developer

    Reputation
    755
    Join Date
    Nov 2006
    Posts
    2,759
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    UINT_PTR, PVOID. Wat? WHY?
    Let your memory library throw exceptions on bad reads / null offsets.

    Code:
    try {
      void* playerBase = memory.read<void*>( memory.read<void*>( memory.readAbsolute<void*>( basePtr ) + basePtrOffset1 ) + basePtrOffset1 );
    }
    catch( ... ) {
       throw BadPlayerBaseException;
    }
    // use playerBase.
    This code you posted there is exactly the reason, why exceptions exist: To separate between the actual execution flow and the error one. Using return values for errors is getting ugly, as you see in your own code.

  4. #4
    flo8464's Avatar Active Member
    Reputation
    30
    Join Date
    Apr 2009
    Posts
    434
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    UINT_PTR, PVOID. Wat? WHY?
    Imho UINT_PTR is fine.
    I don't like using void* when operating on remote memory, as they aren't dereferenceable in the context of the actual process.
    An integer capable to store a memory address is probably the safest and most intuitive solution.

    Let your memory library throw exceptions on bad reads / null offsets.
    I don't think that a read() function should be responsible to determine if the read data makes sense.
    Hey, it compiles! Ship it!

  5. #5
    _Mike's Avatar Contributor
    Reputation
    310
    Join Date
    Apr 2008
    Posts
    531
    Thanks G/R
    0/2
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by flo8464 View Post
    I don't think that a read() function should be responsible to determine if the read data makes sense.
    The original code is only checking for NULL results. And trying to dereference a NULL pointer is normally something you'd throw an exception on, so there would be no loss of data validation.

  6. #6
    schlumpf's Avatar Retired Noggit Developer

    Reputation
    755
    Join Date
    Nov 2006
    Posts
    2,759
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by flo8464 View Post
    Imho UINT_PTR is fine.
    I don't like using void* when operating on remote memory, as they aren't dereferenceable in the context of the actual process.
    An integer capable to store a memory address is probably the safest and most intuitive solution.
    Yes, it should be a size_t. UINT_PTR and PVOID normally are typedefs for unsigned int* and void* though.

  7. #7
    Amrok's Avatar Banned
    Reputation
    4
    Join Date
    Apr 2009
    Posts
    59
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This thread is about complex if statements and not about exception handlers.

    Its ofc a bit hard to understand what im actually doing in the first clause.

    Lets take a closer look:

    if ( !( playerBase ? playerBase = Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset1) : false, playerBase ? playerBase = Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset2) : false ) )

    is the same as:

    if ( ( playerBase ? playerBase = Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset1) : false, playerBase ? playerBase = Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset2) : false ) == NULL )

    now i will try to explain it in words

    playerbasefirst = read(playerbasepointer);
    if ( ( if playerbasefirst > 0 then playerbasesecond = read(playerbasefirst+offset1) ; if playerbasesecond > 0 then playerbasefinal = read(playerbasesecond+offset2) ) == NULL )

    i hope this helps to understand it

    btw: my data types are okay so stop discussing about it. UINT_PTR is just fine for holding a pointer.
    Last edited by Amrok; 08-15-2011 at 06:24 PM.

  8. #8
    jjaa's Avatar Contributor
    Reputation
    245
    Join Date
    Dec 2006
    Posts
    562
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The fact that you need to explain it should give you enough indication that its a bad idea. I disagree with the use of exceptions for this. The read method succeeded in reading the memory, no failure and nothing exceptional about it. I would go with the second one.

  9. #9
    schlumpf's Avatar Retired Noggit Developer

    Reputation
    755
    Join Date
    Nov 2006
    Posts
    2,759
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't really consider this a "complex if statement" but just bad code. If you really want to go with that, use the second expression even though, you want to make this a function of its own and reverse the statements. Positive statements are far easier to read than negative ones.

    Code:
    // read the playerBase
    PVOID getPlayerBase() {
      PVOID playerBase = Memory.ReadOffset<PVOID>(Memory.BaseAddr+PlayerBasePointer);
      if (playerBase)
        playerBase = Memory.ReadOffset<PVOID>(playerBase+PlayerBaseOffset1);
    
      if (playerBase)
        playerBase = Memory.ReadOffset<PVOID>(playerBase+PlayerBaseOffset2);
    
      if (playerBase)
        return playerBase;
    
      Memory._error(7); // Why does Memory care about errors?
    }
    jjaa: Yes, the first read was successful, but a read with a nullpointer given won't. With exceptions, its one statement being clear to read and showing what the intention of the code is. Without, its mostly error checking. I'm not a fan of exceptions myself and rarely use them, but this is just exactly the case where they are way better.

  10. #10
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by schlumpf View Post
    Yes, it should be a size_t. UINT_PTR and PVOID normally are typedefs for unsigned int* and void* though.
    UINT_PTR is a typedef for an unsigned integral type large enough to hold a pointer on the target architecture. It is not a pointer to an unsigned integral type. Common (and understandable due to the name) misconception.

    Originally Posted by Amrok View Post
    What do you think of my way to check if we got a playerBase (only read next pointer if previous pointer reading action was successful):

    ReadOffset returns NULL if it fails.

    Code:
    // read the playerBase
    UINT_PTR playerBase = Memory.ReadOffset<UINT_PTR>(Memory.BaseAddr+PlayerBasePointer);
    if (!(playerBase?playerBase=Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset1):false,playerBase?playerBase=Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset2):false))
        Memory._error(7);
    else
        std::cout << "The playerBase: " << reinterpret_cast<PVOID>(playerBase) << std::endl;
     .
    And this is how it would look like with normal if clauses:

    Code:
    // read the playerBase
    UINT_PTR playerBase = Memory.ReadOffset<UINT_PTR>(Memory.BaseAddr+PlayerBasePointer);
    if (playerBase != NULL)
    {
        playerBase = Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset1);
        if (playerBase != NULL)
            playerBase = Memory.ReadOffset<UINT_PTR>(playerBase+PlayerBaseOffset2);
    }
    
    if (playerBase == NULL)
        Memory._error(7);
    else
        std::cout << "The playerBase: " << reinterpret_cast<PVOID>(playerBase) << std::endl;
    Which way would you prefer?
    Holy shit that first example is ****ing awful. How the **** is anyone supposed to understand what that does at a glance?

    LLVM Coding Standards

  11. #11
    schlumpf's Avatar Retired Noggit Developer

    Reputation
    755
    Join Date
    Nov 2006
    Posts
    2,759
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Cypher View Post
    [COLOR=#00ff00]UINT_PTR is a typedef for an unsigned integral type large enough to hold a pointer on the target architecture. It is not a pointer to an unsigned integral type. Common (and understandable due to the name) misconception.
    I'm not much into windows specific stuff, sorry.
    This then requires that you compile for 32 bit, just as WoW was compiled for. It seems to be more save imho to use a uint32_t then.

  12. #12
    MaiN's Avatar Elite User
    Reputation
    335
    Join Date
    Sep 2006
    Posts
    1,047
    Thanks G/R
    0/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by schlumpf View Post
    I'm not much into windows specific stuff, sorry.
    This then requires that you compile for 32 bit, just as WoW was compiled for. It seems to be more save imho to use a uint32_t then.
    No it doesn't? A 64-bit variable can contain a 32-bit address just fine.
    [16:15:41] Cypher: caus the CPU is a dick
    [16:16:07] kynox: CPU is mad
    [16:16:15] Cypher: CPU is all like
    [16:16:16] Cypher: whatever, i do what i want

  13. #13
    _Mike's Avatar Contributor
    Reputation
    310
    Join Date
    Apr 2008
    Posts
    531
    Thanks G/R
    0/2
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by MaiN View Post
    No it doesn't? A 64-bit variable can contain a 32-bit address just fine.
    Yes, assuming you are only reading 32 bits. But seeing as his ReadOffset is a templated function I think it's safe to assume he is reading sizeof(type) bytes.

  14. #14
    Amrok's Avatar Banned
    Reputation
    4
    Join Date
    Apr 2009
    Posts
    59
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by BaseTsd.h
    #if defined(_WIN64)
    typedef unsigned __int64 UINT_PTR;
    #else
    typedef unsigned int UINT_PTR;
    #endif
    msg2short
    msg2short
    msg2short

  15. #15
    Bananenbrot's Avatar Contributor
    Reputation
    153
    Join Date
    Nov 2009
    Posts
    384
    Thanks G/R
    1/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Without major troubles, you can't inject a x64 dll into x86 wow anyways.
    Also, elighten me on a reason behind targeting a wow bot for x64 nowadays..
    Using UINT_PTR favors code reuse and is therefore only really needed in generic hacks/libraries like HadesMem.

    With regard to a x64 release of wow, it is of course still beneficial to make use of UINT_PTR in all your code, not to mention consistency.

Page 1 of 2 12 LastLast

Similar Threads

  1. Complex Macro Voice Command Made Easy
    By yopilax in forum World of Warcraft Bots and Programs
    Replies: 11
    Last Post: 08-27-2008, 10:23 PM
  2. complex macro voice control
    By yopilax in forum World of Warcraft Exploits
    Replies: 6
    Last Post: 08-26-2008, 04:44 PM
  3. Blizzard makes statement on Gold Buying.
    By Cryt in forum World of Warcraft General
    Replies: 11
    Last Post: 02-23-2008, 10:28 PM
  4. Complex Model editing HELP please
    By Delthar in forum WoW ME Questions and Requests
    Replies: 0
    Last Post: 04-09-2007, 01:59 PM
  5. WoW UI, too complex?
    By Deo in forum World of Warcraft General
    Replies: 9
    Last Post: 02-20-2007, 08:03 PM
All times are GMT -5. The time now is 02:15 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search