Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0E84: Get_Weaponinfo Never Fails to Find a Pointer #14

Open
OrionSR opened this issue Sep 18, 2023 · 9 comments
Open

0E84: Get_Weaponinfo Never Fails to Find a Pointer #14

OrionSR opened this issue Sep 18, 2023 · 9 comments

Comments

@OrionSR
Copy link

OrionSR commented Sep 18, 2023

In an effort to understand and document the use of CLEO+ opcodes for the Sanny Builder Library, I tried and failed to make the get_weaponinfo conditional command return False. It always returns a pointer, even if it points to bogus data.

In particular, weapon skills other than 1 point to the wrong data if the weapon ID is not within the range of skilled weapons - pistol (22) thru tec9 (32).

Similarly, out of range weapon IDs will return invalid pointers as True.

Seemann offered this script at a template for managing get_weaponinfo as a conditional command with standard limits. I'm not sure how modified weapon.dat files or limit adjusters might change these limits.

{$CLEO .cs}
{$USE CLEO+}
0000:
const WEAPON_ID     = 22  //(PISTOL)
const SKILL_LEVEL   = 2 //(PRO)
int weap_info

if
    cleo_call @getweapinfo 2 WEAPON_ID SKILL_LEVEL weap_info
then
    weap_info+=0x20
    int ammo
    read_memory ammo = weap_info 2 false
     
    print_formatted_now "Weapon: %d~n~Skill: %d~n~Ammo: %d" time 3000 WEAPON_ID SKILL_LEVEL ammo
else
    print_formatted_now "Can't get weapon_info for Weapon: %d~n~Skill: %d"  time 3000 WEAPON_ID SKILL_LEVEL
end
terminate_this_custom_script

:getweapinfo
const weaponId = 0@
const skill = 1@
const ptr = 2@

if and
    weaponId >= 0 
    weaponId <= 46
    skill >= 0
    skill <= 3
then
    if skill == 1
    then
        get_weaponinfo weaponId 1 ptr
        cleo_return 1 ptr
    end
    
    if and
        weaponId >= 22 
        weaponId <= 32
    then
        
        if skill == 0
        then weaponId += 25
        end
        
        if skill == 2
        then weaponId += 36
        end
        
        if skill == 3
        then weaponId += 47
        end
        
        get_weaponinfo weaponId 1 ptr
        cleo_return 1 ptr
    end
end
cleo_return 0
@JuniorDjjr
Copy link
Owner

But this script isn't adapted to added weapons without replacing.
Any idea how to make this really modular? The game itself does this limitation somewhere?

@OrionSR
Copy link
Author

OrionSR commented Sep 18, 2023

Not really. Added weapons without replacing is outside of my experience. As it was, it took me a while to come up to speed on a standard WeaponInfo struct enough to explain why I thought my results were... weird. However, Seemann posted this bit that suggests some of these limits are baked into the game code. Would added weapons change these offsets?

CWeaponInfo *__cdecl CWeaponInfo::GetWeaponInfo(eWeaponType weaponID, char skill)
{
  signed __int16 v2; // ax

  v2 = 47;
  switch ( skill )
  {
    case 0:
      return &aWeaponInfo[(weaponID + 25)];
    case 1:
      return &aWeaponInfo[weaponID];
    case 2:
      return &aWeaponInfo[(weaponID + 36)]; <---------------------- WEAPONID + 36
    case 3:
      v2 = weaponID + 47;
      break;
  }
  return &aWeaponInfo[v2]; <----------- default case when skill is not 0..3 (v2=47)
}

My other thought, although not exactly proper, would be to return False data when limits are breached.

I don't have any strong opinions about this, or even a use in mind. My goal is documentation, but I feel obliged to report bugs, or just quirks of the commands when I find them. Thanks for your continued support.

@JuniorDjjr
Copy link
Owner

Checking if result pointer is outside weaponinfo array isn't safe and will basically not help at all.

Since we are simply calling CWeaponInfo::GetWeaponInfo, nothing special on CLEO+ side, the programmer itself need to make sure that the skill value is correct (for example, value previously stored from GetWeaponSkill).

I'll simply limit original weapon types (22-32) because I see no reason not to do this, but it's the programmer's job to use a correct skill ID. I don't see logical cases in which a programmer would invent skill IDs from inside his head, this GET_WEAPONINFO is just a more low level version of GET_CURRENT_CHAR_WEAPONINFO, useful if you need weapon info from previously stored weapon from the char.

But when the skill ID is not known, it is recommended to use "1".
In the new version of CLEO+ I will preserve return boolean, even if it is not really safe.

@OrionSR
Copy link
Author

OrionSR commented Sep 19, 2023

Alright then. I think the best option is to add a more detailed description of this opcode to SBL, documenting the quirks of misuse and the coders responsibility. I'm a little confused about the limit you intend to add but I'll wait for an update and rerun the tests anyway.

Thanks again for the support. I'm bound to have, not necessarily issues, but questions at least, regarding the documentation of some of the more complex CLEO+ opcodes. Are you available for consultation?

@JuniorDjjr
Copy link
Owner

I'm too busy but you can contact me (or even get answers from other people that also knows a bit how to use CLEO+) on #códigos MixMods Discord (the portuguese one, because it's more active, no problem talking in english there).

I started documenting CLEO+ in the Sanny Builder Library before, but while documenting I started to feel Covid symptoms and I felt very sick (weakness, at first I thought I was trying too hard and the page changes made me dizzy etc but no), so I soon stopped for weeks, and I ended up never going back to document it, even though I'm too busy developing my game and such.

But I took the time to do something that I really needed for CLEO+, which are a few dozen more commands that I missed, including a new system that makes it possible to create "render objects" (for peds or other objects) using .dff and .txd without the need to add model IDs . Everything has already been tested a lot, I'm using on Urbanize already and I should release it soon.

So soon you'll have a few dozen more commands to document (and of course, I'll make a summary in the post on the MixMods Forum like I did with the other commands).

@OrionSR
Copy link
Author

OrionSR commented Sep 20, 2023

I'll make a summary in the post on the MixMods Forum

Thanks for this, I found the link to How to create scripts with CLEO+. This will help a lot.

The critical information that I'm often missing is what type of data is being passed. In particular, it is a handle or a pointer? Tracking down enums can sometimes be a time consuming process. Anything you can do to clarify the data types would be appreciated.

I'll follow up on Discord when I run run into trouble. Thanks again.

@JuniorDjjr
Copy link
Owner

JuniorDjjr commented Sep 21, 2023

I'll make a summary in the post on the MixMods Forum

Thanks for this, I found the link to How to create scripts with CLEO+. This will help a lot.

The critical information that I'm often missing is what type of data is being passed. In particular, it is a handle or a pointer? Tracking down enums can sometimes be a time consuming process. Anything you can do to clarify the data types would be appreciated.

I'll follow up on Discord when I run run into trouble. Thanks again.

But on gta3script is already separated handle from pointer (in this case, it's called Entity, for example Entity="CHAR" means a handle of a char, if no Entity is given, it's just a pointer). But in fact everything created by CLEO+ is a pointer to a struct (so modders can easily hack it if needed, I'll always avoid changing struct format).

@OrionSR
Copy link
Author

OrionSR commented Sep 22, 2023

gta3script, another clue. I'll see if I can find the definitions to use as reference.

Did you catch my note on MixMods discord about is_char_really_in_air? It flags the char as in_air while driving, when is_char_in_air does not. Your description didn't mention the exception, which is all I have to judge intent. I didn't want to open another issue if it's working as intended.

@JuniorDjjr
Copy link
Owner

JuniorDjjr commented Sep 22, 2023

gta3script, another clue. I'll see if I can find the definitions to use as reference.

Did you catch my note on MixMods discord about is_char_really_in_air? It flags the char as in_air while driving, when is_char_in_air does not. Your description didn't mention the exception, which is all I have to judge intent. I didn't want to open another issue if it's working as intended.

I said to use the other channel, but replying here: Checking the source code, I think is fine the way it works, otherwise CLEO+ would need to check if inside car then redirect to check if the car is in air instead of char. Looks a bit intrusive when you think about the scripting logic. Under the hood, it simply checks if is hitting a solid surface (so I recommend to use this as description), so if you are on vehicle, the char is not hitting a solid surface and will return false.
Also, there is IS_OBJECT_REALLY_IN_AIR too, but if the object is attached on a car, I think will return false too, and if we change the char to return true, would need to change the object to return true too etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants