eezstreet Posted February 5, 2014 Posted February 5, 2014 So I realize that most people probably don't know a whole lot about C or Angelscript, so I'm taking the time to write a guide, slowly but surely. (If @@Circa or someone would like to pin this, this would be great.) As with all information, you can find the complete guide to Angelscript here. I'd like to break this down into information that's specific to JK2:HD as well as make it a bit easier to understand (as I can personally attribute to this stuff being completely fscking badly written at times). Basic SyntaxFirst, I want to get some basic syntax out of the way. Angelscript is very similar to C and C++, and the syntax as such is pretty much the same. // Anything after a // is considered a comment, and is not processed by the system. // Use these to help others understand your code better, or to temporarily disable parts of code ("commenting out") /* Anything between this notation is also considered a comment. */ /* This syntax for comments can span multiple lines */ int something = 5; // All basic lines must end in a semicolon. if(something == 5) // Parentheses must be closed off something = 6; if(something == 6) { something = 7; } // Likewise, { must be followed by a } at some point. // You can't simply put a } or a ) somewhere either. These will cause the compiler to become confused as it expects a ( or { before them VariablesAngelscript, unlike ICARUS, relies heavily on the concept of variables. There's a few basic types that you should familiarize yourself with.int: The basic number storage unit. Has a maximum size of ~-2 billion to ~2 billion.float: Stores a "floating point" number, in other words, a decimal number such as 4.05 or 2.15. This can also be negative.bool: Stores either a 0 or a 1, representing "true" or "false"string: Stores a number of characters forming words or sentences. For example, "I have a lightsaber!" or "This is a string" or even "cat".There's also a few advanced types and modifiers to the original types:int modifiers: int can be modified to change its maximum storage capacity. As you'll recall, an int can have between -2 billion and 2 billion as values. But there's some reasons why you might want to change this to be smaller or larger. By specifying a power of 2 between 8 and 64, you can change the int's bit size. For example, int8 and int16, which are both smaller than the default amount (-128 to 127 and -32768 to 32767 respectively). There's also int32, which is the same as regular int, as well as int64 which is much, much larger than a regular int. I would avoid using int64, int16 and int8 unless you really need them (such as saving/loading files and networking stuff), so for the most part this isn't really needed. By placing a letter 'u' before 'int', you can specify that the variable is unsigned, or is never negative. This also effectively doubles the maximum size. For instance, uint8 now goes from 0 to 255, and uint32 now goes from 0 to 4 billion. You must specify a size with uints.const: By placing the keyword 'const' before a variable, you specify that the variable cannot be changed. This can be good for a number of reasons, mostly for others understanding your code. You should probably use const whenever you can.double: This is a different type, similar to float. However it uses 64 bits instead of 32 and is therefore more precise.void: This is a unique type which we will discuss later.How about a few examples? int x = 4; // Define a variable named 'x' of type int with a starting value of 4 float y = 4.5; // Define a variable named 'y' of type float with a starting value of 4.5 bool z = true; // Define a bool named 'z' with a starting value of 'true' ObjectsThere is another specific type of variable in Angelscript, called objects. These have a variety of properties, but it's important for the moment to consider these as sorts of containers for other variables. For right now, I won't get too detailed into these, but there's a few objects which you will see throughout the code (such as gentity_t) and it's important to recognize them. Variable NamingThere's a few things that should be noted about variables. First, you cannot start a variable with a number (so 1x would be illegal, but x1 is legal). Variables are also case sensitive. X1 is an entirely different variable from x1. There's also a bunch of names that you can't use as variable names, these are covered here: andboolbreakcasecastclassconstcontinuedefaultdodouble elseenumfalsefinal*floatforfrom*funcdefget*ifimport ininoutintinterfaceint8int16int32int64ismixinnamespace notnulloroutoverride*privatereturnset*shared*super*switchthis*truetypedefuintuint8uint16uint32uint64voidwhilexor MathWe can also do some math: int x = 6; int y = 7; x = y; // x is now 7 x *= y; // x = 7, so 7*7 = 49 x -= y; // x = 49, so 49-7 = 42 y += 10; // y is now 17 x /= 7; // x = 42, so 42/7 = 6 x++; // Increment x by one, so x is now 7 x--; // x is 6 again since we're decreasing by one FunctionsFunctions are chunks of code which get executed by other code. Consider this function: void PrintSomething(string whatToPrint) { Com_Print(whatToPrint); // Print the value of whatToPrint in the console } All this function does is print something in the console, based on what we give to it. While it's really not a good idea to do this per se (why not just use Com_Print?), it does demonstrate the basic idea of a function. You'd then call this function thusly: PrintSomething("Something\n"); or string somethingWeShouldPrint = "Something\n"; PrintSomething(somethingWeShouldPrint); Did you see the void at the beginning of the function? This refers to the return type. You can place a return at any point in the function to "get out of the function" so to speak. void dummy(int someargument) { int something = 6; return; something = 7; // Everything after the return; doesn't occur, so this line doesn't get executed at all. } So what is a return type exactly? Well, a function can return a value based on what its return type is: int dummy2(int someargument) { int something = 6; return something; } int value = dummy2(0); // 'value' now equals 6, since we returned a 6 What about the bit in the ()? Well, these are called parameters. We can pass along some parameters (or none at all!) and the code will use these as variables in the function: int dummy3(int someargument) { return someargument; } int value = dummy3(3); // Value now equals 3, since we passed along a 3, and that got returned to us. Flow of control: if/elseIf you're familiar with ICARUS, you might already know of if/else constructs. if/else is a big construct in nearly every programming language, save for some odd ones like Haskell. When we do an if/else, we're essentially computing a binary instruction which is either true or false. So for instance, if we were to compare: int x = 3; int y = 4; if(x == y) x = 5; // TIP: you do not need to specify {} with if/else if there is only one line in the block else { y = 6; // However if there is more than one line, you must always use {} x = 6; } What happens in this chunk of code? Well, x gets compared to y (note the double == as opposed to =), and if this evaluates to true, the block within gets executed. If not, then the else{} block gets executed. else{} is entirely optional.Here's a slightly more trivial example: bool b = true; if(b) Com_Print("b is true!\n"); else Com_Print("b is false!\n"); What's going on here? We're evaluating what's going on in the (), which in this case happens to be "true" since b equals true. So in this particular example, "b is true!" always gets printed in the console.Okay, here's an even more basic example than that: if(1) Com_Print("Here's some silly line that always gets printed\n"); else Com_Print("Here's some silly line that never gets printed\n"); I want to compound this with another concept, that of else if: int x = 6; int y = 10; if(x == 7) Com_Print("This line doesn't get executed...\n"); else if(y == 10) Com_Print("This one does however!\n"); else Com_Print("Since the else if block got executed, we didn't get to this point.\n"); Reference Structuresvec3_t - VectorsUsed to represent position, direction, etc in 3D space. float x - x position float y - y position float z - z position entityState_t - Entity StateStores savegame information specific to entities int weapon - currently equipped weapon playerState_t - Player StateStores savegame information specific to the player int accuracy_shots - total number of shots fired vec3_t viewangles gclient_t - ClientStores savegame information specific to NPCs and player playerState_t ps gentity_t - EntityBasic unit of an entity. Can be any type (NPC, player, projectile, ...) gclient_t client entityState_t s vec3_t mins - Bounding box vec3_t maxs - Bounding box int damage - Damage dealt (if any) int dflags - Damage flags (if any) int methodOfDeath - Sets method of death (not really used all that much in SP) int clipMask - What the entity collides with int bounceCount - Bouncing (specific to projectiles) Functions void CalcMuzzlePoint(gentity_t@ ent, vec3_t fwd, vec3_t right, vec3_t up, vec3_t muzzle, float lead_in) Calculates an entity's muzzle point, and stores the values in fwd, right, up, and muzzle. lead_in is not used (it's for xbox-related code for autoaiming I think) void Com_Print(string message) Prints a message to the console. int Com_Clampi(int min, int max, int value) float Com_Clamp(float min, float max, float value) Constrains value between min and max and returns the result int Com_AbsClampi(int min, int max, int value) float Com_AbsClamp(float min, float max, float value) Contrains value between min/max, returning the result. Min/Max/Value all use their absolute values (always positive) int Q_irand(int min, int max) float Q_flrand(float min, float max) Returns a random value between min and max (inclusive) float sin(float value) float cos(float value) Standard trigonometry functions int GetWeaponDamage(int weapon) Returns the damage that the weapon does (from the .json file) gentity_t@ CreateMissile(vec3_t start, vec3_t forward, int velocity, int life, gentity_t@ owner) Creates a missile, returning the gentity_t handle of the missile itself. void WP_TraceSetStart(gentity_t@ ent, vec3_t start, vec3_t mins, vec3_t maxs) Given the entity and its start, mins and maxs vectors, sets the start point of the entity (this is to make sure that it doesn't go through walls in some situations) Global Variables - Coordinates for weapon firing - vec3_t wpFwd vec3_t wpRight vec3_t wpUp vec3_t wpMuzzle vec3_t vec3_origin - variable that holds (0, 0, 0) Circa, therfiles and Stoiss like this
Recommended Posts