UGX-Mods Login

or login with an authentication provider below
Sign In with Google
Sign In with Twitter
Sign In with Discord
Sign In with Steam
Sign In with Facebook
Sign In with Twitch

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Cxwh

Awesome tutorial dude :D
9 years ago
So since there are a lot of new people comming to the modding community, I decided to make this small post to help others understand GSC better, anyway lets begin.

Contents:
  • Setting Up
  • Understanding The Syntax
  • Understanding Variables
  • Using 'using' and 'insert'
  • Basic Scripting
  • Threading
  • GSC Functions
  • Cleaning up your script
  • FAQ

Setting Up

Spoiler: click to open...
In order to code GSC you do not need any fancy or pricy programs to do so, all you need is a simple text editor.
If you want you could use the default notepad application that comes with windows but if you prefer something a bit more advanced that has syntax highlighting and some other groovy features then I suggest using some of the programs I have listed below.

Notepad++
Sublime Text
UltraEdit
GSC Studio By iMCSx

I'm sure if you were to do a quick google search you could find more but these are probably the best ones!

Understanding The Syntax

Spoiler: click to open...
If you are new to coding getting your head around the syntax can take quiet a bit of time to get the hang off.
If you are unsure what I mean by "The Syntax" then feel free to google it and come back when you are ready
The Syntax in GSC is similar to most general programming languages such as C++, C#, Ruby and many more.

The 2 Curly Brackets Are Used To Define where the start and end of your functions/statements are.
Code Snippet
Plaintext
Curly Brackets: { }
Example
function funcName()         //'function' Let's Me Define My Function
{              //Starting My Function
                 
}              //Ending It
The Semi-Colon is used to define where a line or statement will end it is also used as a separator in some cases.
Code Snippet
Plaintext
Semi-Colon: ;
Example
funcName(); //By Putting The Semi-Colon I Am Ending My Line/Statement So My Code Knows To Go To The Next Line
Example 2
for (i = 0; i < 10; i++)//In This Example You Can See Im Using The Semi-Colon To Seperate The Variables
{ }
The Brackets are mainly used to indicate an argument, to tell the compiler what data type the function needs to look for first in order to start.
Code Snippet
Plaintext
Brackets: ( )
Example
number = 1;
funcName(number)//Initialising A Function With The Argument being number
//An argument is only to be included if the function supports them if not I would just put brackets with nothing inside

The Square Brackets Are Really Only Used To Declare & Access Arrays
Code Snippet
Plaintext
Square Brackets: [ ]
Example
studentAge["Justin"] = 15;
studentAge["Brandon"] = 16;
number = studentAge["Justin"] //Number would know be equal to 15

Quotation Marks Are Used For Declaring A String
[code]
Code:
Quotation Marks: " "
Example
myName = "Justin"//myName is now equal to Justin

Understanding Variables

Spoiler: click to open...
A Variable is used as a storage point, they are used within almost every programming language and are extremely useful for storing any type of data.
Before declaring a variable you should first know about all the different data types, ill list them below.
Code Snippet
Plaintext
String
Boolean
Float
Integer

There is many more but this is all you will need to know for GSC

Now To declare a variable its actually quiet simple, you don't need to say what type of variable it is you are declaring you just need to put the data in, I'll put some examples below.
Code Snippet
Plaintext
self.stringVariable = "MyString";
self.integerVariable = 1;
self.floatVariable = 1.23;
self.booleanVariable = true;
The names of your variables can be anything you desire, by doing self.variableName I am defining a variable for my own player in GSC, I will talk about this later in Basic Scripting.

Using 'using' and 'insert'

Spoiler: click to open...
I'm sure everyone has seen it when at the top of a GSC code you see something that looks like this
Code Snippet
Plaintext
#using scripts\shared\callbacks_shared
Think of using as a way of copying and pasting, what the above code would be doing is copying and pasting all the contents from another GSC file into our GSC file.
But why would we want to do this? Well the answer to that is quiet simple, so we can use the functions that are in that GSC file in our own GSC file. Insert is basically the same just with variables.

Basic Scripting

Spoiler: click to open...
Now I Will Talk About The Basics of GSC Scripting!

If you have ever seen GSC Coding before I'm sure you are wondering what it means by self and player and all that other stuff that you see before functions.
Well to start off self means the entity/player that is calling the current script, example lets say my player just spawned and I run the code below.
Code Snippet
Plaintext
self freezeControls(true);
Now from what I have told you we know that self is my player because my player is calling this code, so therefore my players controls will be frozen.

Now for a more complex example.
Lets say we have a function with the argument player.
Code Snippet
Plaintext
freezePlayer(player)
{
     player freezeControls(true);
}
Now I'm sure you are wondering how we are supposed to call this if we don't know what to put in the player argument, well ill explain.
There is an array that stores all the players in it, this is what we will use for our argument.
So to call it we could do both ways listed below.
Code Snippet
Plaintext
freezePlayer(level.players[0]); //Freeze Client 0

freezePlayer(self); //Freeze Player Running The Code

Threading

Spoiler: click to open...
Now we know the basics lets move onto something a tiny bit more complex, threading.
Threading is extremely useful within GSC, it is mainly used when doing loops, if we were to create a loop on the main thread we would probably freeze the game, but if we were to make a new thread what would happen is that the main thread would keep running and a new thread would run next to it therefore preventing the game from freezing.

Before creating a new thread that uses a loop there is one thing you should know which is that a loop must have a small wait time, if not your game will lag out and freeze ill provide an example shortly of how to add a wait.

to create a new thread its fairly straight forward all you need to do is put thread infront of where your calling your function.
Code Snippet
Plaintext
function myLoop()//Defining The Function With The Loop
{
     self endon("disconnect");//Ends the thread if player disconnects or dies.
     self endon("death");
     self.number = 1;
     for (;;)
     {
          self.number++; //Increase the number by 1 constantly
          wait 0.05; //stop it from lagging and freezing.
     }
}

//Calling It On A New Thread
self thread myLoop(); //This will make a new thread and run myLoop

GSC Functions

Spoiler: click to open...
I'm not sure if everyone is the same as me but I cant stand seeing ugly codes, this does not mean your code is bad it just makes it harder to understand for others and sometimes for yourself if you want to go back and review it to improve it or check something in it.

Below is an example of what I would call an "ugly" code. (I just used a function I found on NGU and made it ugly)
Code Snippet
Plaintext
play_sound_on_shoot()
{
self endon("disconnect")
self endon("death")
self iPrintln("press shoot button to play a sound");
for(;;)
{
self waittill ("weapon_fired");
self playsound("zmb_cherry_explode");
wait 1;
}
}
Now looking at this code its very hard to read and everything is really close together now below I'm going to show you the neat version of this function
Code Snippet
Plaintext
play_sound_on_shoot()
{
    self endon("disconnect")
    self endon("death")

    self iPrintln("Shoot To Play A Sound!");
    for(;;)
    {
        self waittill ("weapon_fired");
        self PlaySound("zmb_cherry_explode");
        wait 1;
    }
}
You can see I have added indents and changed the iPrintln to something more formal.
If you are unsure how to do your indentations correctly then I will briefly explain.

Indentations are not important and will not affect the way your code functions but like I said before they make your code much more readable and formal. If you are using a text editor like one of the ones I suggested at the start of this tutorial then getting your indentations correct is easy on every keyboard we have a magical button called the "tab button" what this will do is move your writing pointer across a number of spaces depending on where you have pressed tab from.
To indent a function correctly is simple all you have to do is indent your code inside each new code block, example below and further explaination below.



Basically for each code block you define you have to press tab for each code block you are writing in, if you are writing in the main code block you only indent once if you are writing inside a code block thats in the main code block then you indent twice etc.

As for making your code more understandable try to name things to what they are so they make more sense, example below.
Code Snippet
Plaintext
//Lets Compare
self.swagjumpmodeon = true;
//To
self.superJump = true;

//Which one do you understand more? The Bottom One? yea though so...
//Same goes with function names and anything else that requires naming
So just remember to code your functions correctly especially if you are releasing them!

Cleaning up your script

Spoiler: click to open...

Toggles

Cluttered Way
Code Snippet
Plaintext
function godmode_toggle()
{
if(self.godmode == false)
{
self EnableInvulnerability();
self iPrintln("Godmode Enabled");
self.godmode = true;
}
else
{
self DisableInvulnerability();
self iPrintln("Godmode Disabled");
self.godmode = false;
}
}

Clean Way
Code Snippet
Plaintext
function godmode_toggle()
{
if(!isDefined(self.isGod) || !self.isGod)
self EnableInvulnerability();
else
self DisableInvulnerability();

self.isGod = !self.isGod;
self iPrintLn("Godmode " + self.isGod ? "Enabled" : "Disabled");
}
I use this method myself and it is overall better. It may look like more code however the toggle function can be re-used with multiple functions. So instead of writing the same two lines over and over again you have one function that you call that does it for you. As well as the toggle function itself being smaller.


If statements and 'for' loops

Cluttered Way
Code Snippet
Plaintext
if(self.menuOpen == true)
{
for(i = 0; i < level.players.size; i++)
{
level.players[i] iPrintln("Menu is open");
}
}

Clean Way
Code Snippet
Plaintext
if(self.menuOpen)
{
for(i = 0; i < level.players.size; i++)
level.players[i] iPrintln("Menu is open");
}
When using if statements and for loops, you do not need to add braces to your code IF AND ONLY IF the code that you would put between the braces is one line of code. Also you don't need self.menuOpen == true, self.menuOpen by itself works just as fine. If will read the variable as true because if(self.menuOpen) is like saying if(true). Likewise with variables that are false. You don't need self.menuOpen == false, if(!self.menuOpen) will read the variable as false.


Function calling

Cluttered Way
Code Snippet
Plaintext
self thread test();

function test()
{
self iPrintln("I am NOT a looped function");
}

Clean Way
Code Snippet
Plaintext
self thread test();

function test()
{
self iPrintln("I am NOT a looped function");
}

OR
Code Snippet
Plaintext
test();

function test()
{
self iPrintln("I am NOT a looped function");
}

FAQ

Spoiler: click to open...

Q: My Game Freezes On Loading Screen
A: This Means You Either Have A Non-Existant Function or A Syntax Error!

Q: Connection Interrupted then Freeze when calling a function or spawning in
A: This Means You Have A Loop With No Waits

----------------------------------------------------------------------------------------------------------------------------

Credits:
  • Shark
  • Taylor

9 years ago
Is there a way to access/get the price of wallbuys or triggers in general via script?
9 years ago
If you don't want to do this with zones, I'm sure you can do something like this:
Code Snippet
Plaintext
function tp_near_trigger()
{
trigger = GetEnt("NAME OF THE TRIGGER", "targetname");
origin = trigger.origin;

range = 50;
rangeSQ = range**2; //Since we're using distanceSquared

AI = GetAITeamArray("axis");
for(i = 0; i < AI.size; i++)
{
if(isDefined(AI[i].is_brutus))
continue;

if(isDefined(AI[i]) && isAlive(AI[i]))
{
if(DistanceSquared(origin, AI[i].origin) <= rangeSQ)
AI[i] SetOrigin(DESTINATION ORIGIN);
}
}
}
I didn't test this I just though, but you should be able to see what I mean.

Cronex's way is great too

Double Post Merge: December 02, 2016, 06:53:48 pm
Sorry for my typos (not in the code) lol
9 years ago
Sorry, I didn't want to be rude, I just want to help people get the idea of ents and what they're here for
9 years ago
Why did you call 'giveGod' on level? You can also do
Code Snippet
Plaintext
thread giveGod();
9 years ago
The callback
Code Snippet
Plaintext
callback::on_spawned( &on_player_spawned );
The function "on_player_spawned" will be called as soon as "spawned_player" gets notified (will automatically be notified when you spawn) then just add this line to "on_player_spawned":
Code Snippet
Plaintext
self.score = 100*1000;
//self.pers["score"] = 100*1000;
A callback is the same as
Code Snippet
Plaintext
function callback_onSpawn(func)
{
for(;;)
{
self waittill("spawned_player");
self thread [[ func ]](); //func has to be a string now but still works the same
}
}

function callback_onConnect(func)
{
for(;;)
{
level waittill("connected", player);
player thread [[ func ]](); //func has to be a string now but still works the same
}
}

//or you can also do stuff like this
function callback_onGrenadeFire()
{
for(;;)
{
self waittill("grenade_fire", grenade); //you can 'get' entities using these callbacks
grenade EnableLinkTo();

self PlayerLinkToDelta(grenade); //link to the grenade - pitching and rolling will cause the players eye pos to move, but player ent will stay vertical
grenade waittill("explode", position);

self Unlink();
self SetOrigin(position);
}
}
//This is just an example I thought of while making this, I didn't test it or anything but I think it's actually a cool idea :D (useless though)
9 years ago
You don't have to use Dvars to do stuff like this... Try to get creative and work around problems

Call one of them when the trigger gets triggered
Code Snippet
Plaintext
//I'm pretty sure self.god = !self.god works in gsc if not just make a functions that returns the opposite state or bool or idk
function godmode()
{
self.god = !self.god;
if(self.god)
self thread monitor_health();
else
self notify("end_godmode");
self.god = !self.god;
}
function monitor_health()
{
self endon("end_godmode");

self.maxhealth = 9999999;
while(self.health != self.maxhealth)
{
self.health = self.maxhealth;
wait 0.1;
}
}

//or even more simple use engine functions
function godmode()
{
self.god = !self.god;
if(self.god)
self EnableInvulnerability();
else
self DisableInvulnerability();
}
These scripts aslo toggle godmode so you can call them again to disable godmode again
9 years ago
You cannot edit posts until you reach 20 posts on the forum. (Anti spam measure)
I can remove those for you.
Thank's! I'll try and get those 20 points asap :D
9 years ago
If 'certain objects' means trigger this should help you

This is in the Script API Functions (it's c++)
Code Snippet
Plaintext
void <player> PlayHitMarker( <sound name>, <damage state>, <perk feedback>, <is dead> ) //parameters

[MANDATORY] <sound name> The name of the sound or hash //the name of the sound you want to play
[OPTIONAL] <damage state> How damaged the victim is //damage state defines the size of the hitmarker (you cant make it 9999 to make the hitmarker gigantic)
[OPTIONAL] <perk feedback> If the victim had any perks active that modified the hit marker //you get other hitmarkers when you deal explosive damage and the target has flakjacket
[OPTIONAL] <is dead> If the victim has died from this hit marker and needs a red flash //makes the hitmarker red

CATEGORY: Player
CLIENT/SERVER: Server
SUMMARY: Plays a hit marker event
EXAMPLE: self PlayHitMarker( "evt_squad_activate", 3, "flakjacket" )
You can or should always check the 'bo3_scriptapifunctions.htm' file which was included in the mod tools for api/engine functions
Code Snippet
Plaintext
function example()
{
triggers = GetEntArray(ents, "targetname"); //replace 'ents' with the array name of all triggers that should play a hitmarker
foreach(trigger in triggers)
{
trigger waittill("trigger", player);
player PlayHitMarker("mpl_hit_alert"); //mpl_hit_alert is the standart hitmarker sound
}
}

//if you want to do this for only one trigger
function example()
{
triggers = GetEnt(name, "targetname"); //replace 'name' with the name of the trigger that should play a hitmarker
trigger waittill("trigger", player);
player PlayHitMarker("mpl_hit_alert"); //mpl_hit_alert is the standart hitmarker sound
}
9 years ago
I'm new to UGX and I don't know how to edit posts (if I even can) so I apologise for the [INDENT] tags throughout this post
9 years ago
This hides every hud element created for the player ( self )
Code Snippet
Plaintext
self SetClientUIVisibilityFlag( "hud_visible", 0 );
So you just call it once all hud elements are created

What JBird meant is something I like to do
Code Snippet
Plaintext
//first I hide all hud elements that have been created
self SetClientUIVisibilityFlag( "hud_visible", 0 );

//then I can 'draw' my own hud
level.round_count = level drawValue(2, 69, level.round_number, "LEFT", "BOTTOM", 0, 0, 1, (1, 1, 1), true) //you would have to update the value but this is just an example anyways

function drawValue(fontSize, sorts, value, align, relative, x, y, alpha, color, all = false)
{
    if(all == true) //you can also do if(all) or if(all == 1)
    uiElement = level hud::createServerFontString("default", fontSize);
    else
    uiElement = self hud::createFontString("default", fontSize);
   
    uiElement hud::setPoint(align, relative, x, y);
    uiElement setvalue(value);
    uiElement.sort = sorts;
    uiElement.hidewheninmenu = true;
    uiElement.alpha = alpha;
    uiElement.color = color;
    return uiElement;
}
All hud elements created after SetClientUIVisibilityFlag will be shown to the player and simply do this to show the hud again
Code Snippet
Plaintext
self SetClientUIVisibilityFlag( "hud_visible", 1 ); //0 - hide, 1 - show
9 years ago
Have you tried to use
Code Snippet
Plaintext
zm_weapons::weapon_give(weaponobject);
It does a lot more checks, and I think one of them will handle mule kick and if player has max weapons.


And are you using the do_knucke_crack from _zm_pack_a_punch.gsc? I would assume they have compensated for that issue in there, most likely using the zm_utility::increment_is_drinking() function, and the zm_utility::decrement_is_drinking() one.

Code Snippet
Plaintext
workbench waittill("trigger",player);

player thread _zm_pack_a_punch::do_knuckle_crack();
wait(2.7);
player playLocalSound("zmb_cha_ching");
player zm_weapons::weapon_give(getWeapon(level.weaponGiven));
player switchtoweapon(getweapon(level.weaponGiven));
You won't be able to do so since all functions in '_zm_pack_a_punch' are private, atleast I think so (and it also #namespace isn't used)
9 years ago
Okay so I'm fairly new to zombie modding, but I used to code BO2 GSC and now since BO3 Modtools were released I decided to come back to modding :D

So my main questions are:
How do I get the costs of an trigger? (.costs is just made up)
 How do I make it so that the trigger doesn't cost anything for only me?

Spoiler: click to open...
Shopping Free
Code Snippet
Plaintext
//bgb shopping free
function bgb_shopping_free()
{
    self endon("bgb_done");

    self thread wait_notify(60, "bgb_done"); //1min
    self thread waittill_call("bgb_done", "reset_triggers");

    self.shopping_free = true;
    setdvar("zombie_unlock_all", 1);

    self.triggers = strTok("zombie_doors, zombie_door, zombie_airlock_buy, zombie_debris, flag_blocker, window_shutter", ", ");
    wait 0.1;

    foreach(trigger in triggers)
    {
        trigger_ent = GetEntArray(trigger, "targetname");
        for(i = 0; i < trigger_ent.size; i++)
        {
            trigger_ent[i].old_costs = trigger_ent[i].costs;
            trigger_ent[i].costs = 0;
            trigger_ent[i].was_player_triggered = false;
           
            //add check if player is self
            trigger_ent[i] waittill("trigger", player);
            trigger_ent[i].was_player_triggered = true;
        }
    }
}

function reset_triggers()
{
    triggers = self.triggers;
    foreach(trigger in triggers)
    {
        trigger_ent = GetEntArray(trigger, "targetname");
        for(i = 0; i < trigger_ent.size; i++)
        {
            if( !trigger_ent[i].was_player_triggered )
                trigger_ent[i].costs = trigger_ent[i].old_costs;
        }
    }
    wait 0.1;

    if(!self others_have_shopping_free())
        setdvar("zombie_unlock_all", 0);
    self.triggers = undefined;
}

function others_have_shopping_free()
{
    players = GetPlayers(self.team);
    foreach(player in players)
    {
        if(player == self)
            continue;

        if(player.shopping_free)
            return true;
        else
            result = false;
    }
    return result;
}

function wait_notify(time, event)
{
    wait time;
    self notify(event);
}

function waittill_call(event, func, arg1, arg2)
{
    self waittill(event);

    if(isDefined( arg1 ) && isDefined( arg2 ))
        self thread [[ func ]](arg1, arg2);

    else if(isDefined( arg1 ) && !isDefined( arg2 ))
        self thread [[ func ]](arg1);

    else
        self thread [[ func ]]();
}

And I'm trying to make my own gobblegums (bgbs) and I made this script but I don't know the names of the fxs/sounds, can someone help me with it or show me a way to work around it?

This is more of a random question
Are there any effects for stuff like the electric cherry electricity/blast furnace? (sound, fx)

Spoiler: click to open...
Has no name yet
Code Snippet
Plaintext
//new bgb
function have_not_found_a_name_yet()
{
    self endon("bgb_done");

    range = 120;
    rangeSQ = range*range; //since we're using distanceSquared
    self thread electrocuting_ambient(range);

    //time = &RandomIntRange(1, 3); //would be better because i wont get results like 0.11
    time = &RandomFloatRange(0.1, 0.3);
    self waittill("player_used_bgb");

    AI = GetAITeamArray("axis");
    AI = self getClosest(AI, rangeSQ);
    for(i = 0; i < AI.size; i++)
    {
        AI[i] FreezeControls(true); //idk how to freeze a zombie lol
        fx_duration = RandomFloatRange(0.1, 0.3);

        wait time; //or time/10 if I use IntRange
        self notify("electrocuting_zombies");

        while(fx_duration <= 0)
        {
            //bo2's fx - don't know bo3's fx
            PlayFxOnTag(level._effect["prox_grenade_player_shock"], AI[i], "j_head");
            PlayFxOnTag(level._effect["prox_grenade_player_shock"], AI[i], "J_Spine1");
            PlayFxOnTag(level._effect["prox_grenade_player_shock"], AI[i], "J_Spine4");
            PlayFxOnTag(level._effect["prox_grenade_player_shock"], AI[i], "pelvis");
            fx_duration -= 0.09; //just to add more randomness
            wait 0.05;
        }
        wait 0.05;
        AI[i] FreezeControls(false);
        AI[i] DetachAll();
        AI[i] DoDamage(AI[i].health + 1, self.origin, self);
        self zm_score::add_to_player_score(100); //or less idk
    }
}

function electrocuting_ambient(range)
{
    self endon("bgb_done");

    self waittill("electrocuting_zombies");
    pos = self.origin;

    PlaySoundAtPosition("wpn_taser_mine_zap", pos); //bo2's sound
    Earthquake(0.22, 0.4, pos, range);
}

function getClosest(ents, rangeSQ, is_squared = true) //SQ = squared
{
    index = 0;
    newArr = []

    if(!is_squared)
        rangeSQ *= rangeSQ;

    for(i = 0; i < ents.size; i++)
    {
        if(DistanceSquared(self.origin, ents[i].origin) <= rangeSQ)
        {
            newArr[index] = ents[i];
            index++;
        }
    }
    return newArr;
}
I would be thankfull for any help I can get!
9 years ago
Loading ...