Results 1 to 3 of 3

Thread: [Tutorial] settext() without precaching

  1. #1
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts

    [Tutorial] settext() without precaching

    Heres a small tutorial for you all.

    It will allow you to settext() to any clienthudelem any string you desire.

    Known bugs: does not work properly with killcam and .archived = true (so set .archived to false if you use killcam, or just dont use it all together )

    Background:
    Spoiler:

    Configstrings:
    CoD2 precaching fills an array of configstrings with information. Precachetext(&"Hello world") will write "Hello world" to a semi-random configstring number.
    When a client connects to a server, all configstrings are synced to this client.
    CoD2 does not allow for precaching after frame 1, but we CAN change the value the CLIENT has in his configstring by using sendgameservercommand(entnum, "d [number] [newvalue]")
    This will overwrite the "Hello world" clientside with another string, which will propagate to any hud that was called with settext(&"Hello world") immediately.
    So all we need to do is precache a bunch of strings, find their configstring number and when we wanna settext() the hud, instead of settext()-ing it, we just simply send a gameservercommand to change the client's configstring.


    Ok, on to the code:
    Spoiler:

    PHP Code:
    init()
    {
        
    level.inf_hud_str = [];
        for(
    032i++)
        {
            
    level.inf_hud_str[i] = spawnstruct();
            
    level.inf_hud_str[i].locstr findlocstr(i);
            
    level.inf_hud_str[i].str findstr(i);
            
    precachestring(level.inf_hud_str[i].locstr);
            
    level.inf_hud_str[i].index G_FindConfigstringIndex(level.inf_hud_str[i].str1310256);
        }
        
    level thread waitforconnect();
    }

    createinfhud(num)
    {
        
    hud newclienthudelem(self);
        
    hud.infhudindex num;
        
    hud.owner self;
        
    self.infhudlist[num] = hud;
        
    hud settext(level.inf_hud_str[num].locstr);
        
    hud.alpha 0;
        
    hud.txt "";
        return 
    hud;
    }

    setinftext(txt)
    {
        
    player self.owner;
        
    index level.inf_hud_str[self.infhudindex].index;
        
    sendgameservercommand(player getentitynumber(), "d " index " " txt);
        if(!
    isdefined(self.archived) || self.archived)
        {
            
    specs player getspectators();
            for(
    0specs.sizei++)
                
    sendgameservercommand(specs[igetentitynumber(), "d " index " " txt);
        }
        
    self.txt txt;
    }

    waitforconnect()
    {
        while(
    true)
        {
            
    level waittill("connecting"player);
            
    player playerinit();
        }
    }

    waitforspec()
    {
        
    self endon("disconnect");
        while(
    true)
        {
            
    self waittill("spawned");
            if(
    self.pers["team"] == "spectator")
                
    self thread onspec();
        }
    }

    playerinit()
    {
        
    self.infhudlist = [];
        
    self thread waitforspec();
    }

    findstr(i)
    {
        return 
    "JumpersHeavenHudValue" i;
    }

    findlocstr(i)
    {
        switch(
    i)
        {
            case 
    0: return &"JumpersHeavenHudValue0";
            case 
    1: return &"JumpersHeavenHudValue1";
            case 
    2: return &"JumpersHeavenHudValue2";
            case 
    3: return &"JumpersHeavenHudValue3";
            case 
    4: return &"JumpersHeavenHudValue4";
            case 
    5: return &"JumpersHeavenHudValue5";
            case 
    6: return &"JumpersHeavenHudValue6";
            case 
    7: return &"JumpersHeavenHudValue7";
            case 
    8: return &"JumpersHeavenHudValue8";
            case 
    9: return &"JumpersHeavenHudValue9";
            case 
    10: return &"JumpersHeavenHudValue10";
            case 
    11: return &"JumpersHeavenHudValue11";
            case 
    12: return &"JumpersHeavenHudValue12";
            case 
    13: return &"JumpersHeavenHudValue13";
            case 
    14: return &"JumpersHeavenHudValue14";
            case 
    15: return &"JumpersHeavenHudValue15";
            case 
    16: return &"JumpersHeavenHudValue16";
            case 
    17: return &"JumpersHeavenHudValue17";
            case 
    18: return &"JumpersHeavenHudValue18";
            case 
    19: return &"JumpersHeavenHudValue19";
            case 
    20: return &"JumpersHeavenHudValue20";
            case 
    21: return &"JumpersHeavenHudValue21";
            case 
    22: return &"JumpersHeavenHudValue22";
            case 
    23: return &"JumpersHeavenHudValue23";
            case 
    24: return &"JumpersHeavenHudValue24";
            case 
    25: return &"JumpersHeavenHudValue25";
            case 
    26: return &"JumpersHeavenHudValue26";
            case 
    27: return &"JumpersHeavenHudValue27";
            case 
    28: return &"JumpersHeavenHudValue28";
            case 
    29: return &"JumpersHeavenHudValue29";
            case 
    30: return &"JumpersHeavenHudValue30";
            case 
    31: return &"JumpersHeavenHudValue31";
        }
    }

    onspec()
    {
        if(
    isdefined(self.spectator_handling_running) && self.spectator_handling_running)
            return;
        
    self.spectator_handling_running true;

        
    old_spectator_client self;
        while(
    isdefined(self) && (!isdefined(self.sessionstate) || self.sessionstate == "spectator"))
        {
            
    spectator_client self getSpectatorClient();
            if(
    old_spectator_client != spectator_client)
            {
                if(
    isdefined(spectator_client) && spectator_client != self)
                {
                    for(
    032i++)
                    {
                        if(
    isdefined(spectator_client.infhudlist[i]) && (!isdefined(spectator_client.infhudlist[i].archived) || spectator_client.infhudlist[i].archived))
                            
    sendgameservercommand(self getentitynumber(), "d " level.inf_hud_str[spectator_client.infhudlist[i].infhudindex].index " " spectator_client.infhudlist[i].txt);
                    }
                }
                
    old_spectator_client spectator_client;
            }
            
    wait 0.05;
        }
        if(
    isdefined(self))
            
    self.spectator_handling_running false;
    }

    getspectators()
    {
        
    spectators = [];
        
    players getentarray("player""classname");
        for(
    0players.sizei++)
        {
            if(
    isdefined(players[i].pers["team"]) && players[i].pers["team"] == "spectator")
            {
                
    speccing players[igetspectatorclient();
                if(
    isdefined(speccing) && speccing == self)
                    
    spectators[spectators.size] = players[i];
            }
        }
        return 
    spectators;



    Looks like an aweful lot of code, but it isnt.

    All you need to know is:
    PHP Code:
    newclienthudelem() is replaced (and wrappedby createinfhud(num)
    settext() is replaced (but not wrappedby setinftext(txt)
    init() needs to be called ongamestart
    You need a libcod version that supports G_FindConfigstringIndex
    () 
    So, you manually need to find a free index for the createinfhud. I suggest you do this statically so all clients have the same hud associated with the same configstring (eg self.statshud = createinfhud(13) for all clients) This will then return a hud element which can be used with hud setinftext("any string that isnt localized and is under 256 characters long");

    Thats all
    Have fun with it
    Last edited by IzNoGoD; 29th December 2014 at 13:57.
    "Does not work" is an error report for a bug between keyboard and chair.

    All hail Artie Effem

  2. The Following 10 Users Say Thank You to IzNoGoD For This Useful Post:

    caldas (14th June 2018),filthy_freak_ (29th December 2014),kung foo man (29th December 2014),Mitch (29th December 2014),Ni3ls (29th December 2014),Peterlankton (29th December 2014),serthy (29th December 2014),Spike (29th December 2014),ysniper (26th January 2019),YuriJurek (2nd May 2016)

  3. #2
    Assadministrator kung foo man's Avatar
    Join Date
    Jun 2012
    Location
    trailerpark
    Posts
    2,011
    Thanks
    2,102
    Thanked 1,084 Times in 753 Posts
    Nice wrapper

    Uploaded the new binaries: http://killtube.org/downloads/libcod/2014_12_29/ (last upload was 7 months ago, lol)

    Yesterday I've finally merged Mitch's repo with like 70 new commits (basically just copied it, since Mitch merged my last 2 commits from some months ago).

    Now my repo is 5 commits ahead with:

    Click image for larger version. 

Name:	repo.png 
Views:	222 
Size:	49.9 KB 
ID:	814

    The dummy-replacement-function for the "does the mapname exist-function" in setmapnamestring() was the first try to get this done, but it didn't work out well, because the 2nd hud would overwrite the value of the first one.

    Now we added G_FindConfigstringIndex() and G_FindConfigstringIndexOriginal() for all three CoD2 versions.

    G_FindConfigstringIndex(): does not crash, but can't create new configstrings also and can be used for non-precached shaders (ask IzNoGod, just played with strings yet)
    G_FindConfigstringIndexOriginal(): can crash, but might become useful for somebody, as it is the original function

    Regarding forum: I've added [spoiler][/spoiler] tag
    timescale 0.01

  4. The Following 3 Users Say Thank You to kung foo man For This Useful Post:

    Mitch (29th December 2014),Ni3ls (29th December 2014),serthy (29th December 2014)

  5. #3
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    Heres a libcod build with the G_FindConfigstringIndex(), but without G_FindConfigstringIndexOriginal()

    https://www.dropbox.com/s/kf36aak3qj...12_29.zip?dl=0

    (you can use this version with the infinite-settext)
    "Does not work" is an error report for a bug between keyboard and chair.

    All hail Artie Effem

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •