| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788 |
- /*
- Legal:
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 the "License"; you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is the YSI framework.
-
- The Initial Developer of the Original Code is Alex "Y_Less" Cole.
- Portions created by the Initial Developer are Copyright C 2011
- the Initial Developer. All Rights Reserved.
- Contributors:
- Y_Less
- koolk
- JoeBullet/Google63
- g_aSlice/Slice
- Misiur
- samphunter
- tianmeta
- maddinat0r
- spacemud
- Crayder
- Dayvison
- Ahmad45123
- Zeex
- irinel1996
- Yiin-
- Chaprnks
- Konstantinos
- Masterchen09
- Southclaws
- PatchwerkQWER
- m0k1
- paulommu
- udan111
- Thanks:
- JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
- ZeeX - Very productive conversations.
- koolk - IsPlayerinAreaEx code.
- TheAlpha - Danish translation.
- breadfish - German translation.
- Fireburn - Dutch translation.
- yom - French translation.
- 50p - Polish translation.
- Zamaroht - Spanish translation.
- Los - Portuguese translation.
- Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
- me to strive to better.
- Pixels^ - Running XScripters where the idea was born.
- Matite - Pestering me to release it and using it.
- Very special thanks to:
- Thiadmer - PAWN, whose limits continue to amaze me!
- Kye/Kalcor - SA:MP.
- SA:MP Team past, present and future - SA:MP.
- Optional plugins:
- Gamer_Z - GPS.
- Incognito - Streamer.
- Me - sscanf2, fixes2, Whirlpool.
- */
- PRE_HOOK(Class)
- #undef CHAIN_ORDER
- #define CHAIN_ORDER @CO_Class
- forward Class_ResolveGroups(class, Group:forgroup, bool:cp);
- enum e_CLASS_FLAGS (<<= 1)
- {
- e_CLASS_FLAGS_SKIN = 0x0000FFFF,
- e_CLASS_FLAGS_ENABLED = 0x00010000,
- e_CLASS_FLAGS_ACTIVE
- }
- enum E_CLASS
- {
- e_CLASS_FLAGS:E_CLASS_FLAGS,
- Float:E_CLASS_X,
- Float:E_CLASS_Y,
- Float:E_CLASS_Z,
- Float:E_CLASS_A,
- E_CLASS_WEAPONS[MAX_CLASS_SPAWN_WEAPONS + 1],
- Group:E_CLASS_GROUP,
- PlayerArray:E_CLASS_PLAYERS<MAX_PLAYERS>
- }
- static stock
- YSI_g_sClasses[MAX_CLASSES][E_CLASS],
- YSI_g_sPlayerClass[MAX_PLAYERS],
- YSI_g_sInternalClass[MAX_PLAYERS],
- YSI_g_sClassCount,
- YSI_g_sLastRefuse[MAX_PLAYERS];
- stock Class_ResolveGroups(class, Group:forgroup, bool:cp) <YSI_has_groups : n>
- {
- #pragma unused forgroup
- P:2("Class_ResolveGroups<n>: call Resolve %d %d %d", class, _:forgroup, cp);
- if (!cp) PA_Init(YSI_g_sClasses[class][E_CLASS_PLAYERS], true);
- }
- stock Class_ResolveGroups(class, Group:forgroup, bool:cp) <>
- {
- #pragma unused forgroup
- P:2("Class_ResolveGroups<>: call Resolve %d %d %d", class, _:forgroup, cp);
- if (!cp) PA_Init(YSI_g_sClasses[class][E_CLASS_PLAYERS], true);
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to check if active.</param>
- *//*------------------------------------------------------------------------**/
- P:D(bool:_Class_IsActive(classid));
- #define _Class_IsActive(%1) (YSI_g_sClasses[(%1)][E_CLASS_FLAGS] & e_CLASS_FLAGS_ACTIVE)
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to check if valid.</param>
- *//*------------------------------------------------------------------------**/
- P:D(bool:_Class_IsValid(classid));
- #define _Class_IsValid(%1) (IS_IN_RANGE((%1), 0, MAX_CLASSES) && _Class_IsActive(%1))
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to check.</param>
- *//*------------------------------------------------------------------------**/
- P:D(bool:_Class_Enabled(classid));
- #define _Class_Enabled(%1) (YSI_g_sClasses[(%1)][E_CLASS_FLAGS] & e_CLASS_FLAGS_ENABLED)
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to get X location for.</param>
- *//*------------------------------------------------------------------------**/
- P:D(Float:Class_X(classid));
- #define Class_X(%1) YSI_g_sClasses[(%1)][E_CLASS_X]
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to get Y location for.</param>
- *//*------------------------------------------------------------------------**/
- P:D(Float:Class_Y(classid));
- #define Class_Y(%1) YSI_g_sClasses[(%1)][E_CLASS_Y]
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to get Z location for.</param>
- *//*------------------------------------------------------------------------**/
- P:D(Float:Class_Z(classid));
- #define Class_Z(%1) YSI_g_sClasses[(%1)][E_CLASS_Z]
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to get angle for.</param>
- *//*------------------------------------------------------------------------**/
- P:D(Float:Class_A(classid));
- #define Class_A(%1) YSI_g_sClasses[(%1)][E_CLASS_A]
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to get skin for.</param>
- *//*------------------------------------------------------------------------**/
- P:D(Class_Skin(classid));
- #define Class_Skin(%1) (YSI_g_sClasses[(%1)][E_CLASS_FLAGS] & e_CLASS_FLAGS_SKIN)
- /*-------------------------------------------------------------------------*//**
- * <remarks>
- * Creates three real player classes so you can scroll correctly with the
- * direction being detected.
- * </remarks>
- * <transition keep="true" target="_YCM : u"/>
- * <transition keep="true" target="_YCM : y"/>
- *//*------------------------------------------------------------------------**/
- hook OnScriptInit()
- {
- #if !_YSIM_IS_CLIENT
- if (!YSI_FILTERSCRIPT)
- {
- // This code placement is not generic.
- new
- classLeft = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0),
- classMiddle = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0),
- classRight = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
- if (classLeft != 0 || classMiddle != 1 || classRight != 2)
- {
- P:E("y_classes assumptions failed. Do you have \"AddPlayerClass\" in your modes?");
- }
- //printf("==========================");
- P:4("Class_OnScriptInit: classes = %d %d %d", classLeft, classMiddle, classRight);
- //printf("==========================");
- #if !defined YSI_NO_MASTER
- if (_Master_Get(#_YCM, true))
- {
- // Nothing changed, or we took it without force.
- state _YCM:y;
- _YCM@ = _E_YCM@y;
- }
- else
- {
- // Something changed, tell other scripts.
- state _YCM:u;
- _YCM@ = _E_YCM@u;
- // Determine the next unique name.
- CallRemoteFunction(#_YCM, "");
- // There is a note in y_master about this being safe
- // because servers always get the data. This is the server
- // code, but may be in use by cloud systems. This, however,
- // is still not a problem because we never fully pass off.
- }
- #endif
- }
- #endif
- return 1;
- }
- static stock Class_FindNew(playerid, playerclass, dir)
- {
- P:4("Class_FindNew called: %i, %i, %i", playerid, playerclass, dir);
- if (dir == 0)
- {
- // No change, check the current skin is still valid. There are plenty
- // of reasons for this: Removed skin, returned -1, disabled, returned to
- // class selection. This used to not be handled explicitly, but now it
- // is.
- if (_Class_Enabled(playerclass) && PA_Get(YSI_g_sClasses[playerclass][E_CLASS_PLAYERS], playerid)) return playerclass;
- ++dir;
- }
- new
- old = playerclass % YSI_g_sClassCount;
- do
- {
- playerclass = (playerclass + dir) % YSI_g_sClassCount;
- P:4("Class_FindNew: %d %d", playerclass, playerid);
- }
- while (playerclass != old && (!_Class_Enabled(playerclass) || !PA_Get(YSI_g_sClasses[playerclass][E_CLASS_PLAYERS], playerid)));
- // (!(playerclass == old || (_Class_Enabled(playerclass) && PA_Get(YSI_g_sClasses[playerclass][E_CLASS_PLAYERS], playerid))))
- return playerclass;
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="playerid">Player who is changing class.</param>
- * <param name="playerclass">The internal class they are switching to.</param>
- * <remarks>
- * Does the visual faking through "SetPlayerSkin", and also calls
- * "SetSpawnInfo" to avoid any lag from "SetPlayerPos" under "OnPlayerSpawn".
- * </remarks>
- *//*------------------------------------------------------------------------**/
- foreign void:Class_Goto(playerid, playerclass);
- global void:Class_Goto(playerid, playerclass)
- {
- P:2("Class_Goto called: %i, %i", playerid, playerclass);
- // This now sets the REAL spawn information, including spawn location.
- SetSpawnInfo(playerid, NO_TEAM, Class_Skin(e_PLAYER_CLASS:playerclass), Class_X(e_PLAYER_CLASS:playerclass), Class_Y(e_PLAYER_CLASS:playerclass), Class_Z(e_PLAYER_CLASS:playerclass), Class_A(e_PLAYER_CLASS:playerclass), 0, 0, 0, 0, 0, 0);
- SetPlayerSkin(playerid, Class_Skin(e_PLAYER_CLASS:playerclass));
- YSI_g_sPlayerClass[playerid] = playerclass; //(YSI_g_sPlayerClass[playerid] & ~e_PLAYER_CLASS_SKIN) | (e_PLAYER_CLASS:playerclass);
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="playerid">Player who selected a spawn.</param>
- * <remarks>
- * Has inbuilt protection for a bug where selections aren't correctly
- * debounced so you can press shift twice at once which can mess up some
- * scripts (e.g. the example team selection script). Calls
- * OnPlayerRequestSpawnEx with an additional class parameter.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- #if !defined YSI_NO_MASTER && (_YSIM_IS_CLIENT || _YSIM_IS_STUB)
- public OnPlayerRequestSpawn(playerid)
- {
- return 1;
- }
- #else
- #if !defined YSI_NO_MASTER && _YSIM_IS_CLOUD
- public OnPlayerRequestSpawn(playerid) <>
- {
- return 1;
- }
-
- public OnPlayerRequestSpawn(playerid) <_YCM:y>
- #else
- public OnPlayerRequestSpawn(playerid)
- #endif
- {
- P:1("Class_OnPlayerRequestSpawn called: %d", playerid);
- new
- time = GetTickCount();
- if ((time - YSI_g_sLastRefuse[playerid]) >= 500)
- {
- new
- ret = CallRemoteFunction("Class_OnPlayerRequestSpawn", "i", playerid);
- P:4("Class_OnPlayerRequestSpawn() return: %d", ret);
- if (ret)
- {
- new
- Group:newgroup = YSI_g_sClasses[YSI_g_sPlayerClass[playerid]][E_CLASS_GROUP];
- P:4("Class_OnPlayerRequestSpawn() newgroup: %d", _:newgroup);
- if (newgroup != Group:-1) Class_ResolveGroups(playerid, newgroup, true);
- if (ret == -1)
- {
- // Send the player back to class selection.
- _Class_OnPlayerRequestClass(playerid, YSI_g_sInternalClass[playerid]);
- }
- else
- {
- return 1;
- }
- }
- }
- P:5("Class_OnPlayerRequestSpawn: Return 0");
- return
- YSI_g_sLastRefuse[playerid] = time,
- 0;
- }
- #endif
- HOOK_FORWARD:Class_OnPlayerRequestSpawn(playerid);
- #if defined _ALS_OnPlayerRequestSpawn
- #undef OnPlayerRequestSpawn
- #else
- #define _ALS_OnPlayerRequestSpawn
- #endif
- #define OnPlayerRequestSpawn(%0) Class_OnPlayerRequestSpawn(%0) <_ALS : _ALS_go>
- /*-------------------------------------------------------------------------*//**
- * <param name="playerid">Player who spawned.</param>
- * <remarks>
- * Sets a player's position based on skin.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- mhook OnPlayerSpawn(playerid)
- {
- P:2("Class_OnPlayerSpawn called: %d", playerid);
- new
- playerclass = YSI_g_sPlayerClass[playerid],
- weapon;
- for (new i = 0; i != MAX_CLASS_SPAWN_WEAPONS; ++i)
- {
- weapon = YSI_g_sClasses[playerclass][E_CLASS_WEAPONS][i];
- if (weapon)
- {
- GivePlayerWeapon(playerid, weapon & 0xFF, weapon >>> 8);
- }
- else
- {
- break;
- }
- }
- weapon = YSI_g_sClasses[playerclass][E_CLASS_WEAPONS][MAX_CLASS_SPAWN_WEAPONS];
- P:5("Class_OnPlayerSpawn: Armour %d %d %d", weapon, weapon & 0xFF, WEAPON_ARMOUR);
- if ((weapon & 0xFF) == WEAPON_ARMOUR)
- {
- weapon >>>= 8;
- if (weapon == 0x00800000)
- {
- // INFINITY
- SetPlayerArmour(playerid, Float:0x7F800000);
- }
- else
- {
- SetPlayerArmour(playerid, weapon);
- }
- }
- return 1;
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="playerid">Player who joined the server.</param>
- * <remarks>
- * Reset all the data on this player's current classes.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- mhook OnPlayerConnect(playerid)
- {
- YSI_g_sPlayerClass[playerid] = -1,
- YSI_g_sInternalClass[playerid] = -1;
- NO_GROUPS()
- {
- new
- slot = PA_Slot(playerid),
- Bit:mask = PA_Mask(playerid);
- for (new i = 0; i != MAX_CLASSES; ++i)
- {
- YSI_g_sClasses[i][E_CLASS_PLAYERS][slot] |= mask;
- }
- }
- return 1;
- }
- /*-------------------------------------------------------------------------*//**
- * <remarks>
- * Converts the variable arguments to an array.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- #define _CLASS_WEAPON_CODE \
- {if((n-w+1)/2>MAX_CLASS_SPAWN_WEAPONS) P:E("Excessive class weapon data."); \
- if((n-w)&0x01){while(w!=n)if((cw=getarg(w++))==WEAPON_ARMOUR)weapons[MAX_CLASS_SPAWN_WEAPONS]=WEAPON_ARMOUR|(100<<8);else if(w==n)P:E(": Insufficient class weapon data.");else weapons[s++]=(cw&0xFF)|(getarg(w++)<<8);} \
- else{while(w!=n)weapons[((cw=getarg(w++))==WEAPON_ARMOUR)?MAX_CLASS_SPAWN_WEAPONS:(s++)]=(cw&0xFF)|(getarg(w++)<<8);}}
- /*-------------------------------------------------------------------------*//**
- * <param name="skin">Skin of the class.</param>
- * <param name="x">X spawn location.</param>
- * <param name="y">Y spawn location.</param>
- * <param name="z">Z spawn location.</param>
- * <param name="a">A spawn location.</param>
- * <param name="">Spawn weapons and ammo (weapon then ammo)</param>
- * <remarks>
- * Pretty much AddPlayerClass but allows greater control over the classes.
- * Now has infinate (MAX_CLASS_SPAWN_WEAPONS) spawn weapons. This is one of
- * the few API functions which is not entirely remote. This is because it has
- * variable parameters which is need to collect in to a single array to pass to
- * the remote function.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- stock Class_Add(skin, Float:x, Float:y, Float:z, Float:a, ...)
- {
- P:3("Class_Add called: %i, %f, %f, %f, %f, (+%i)", skin, x, y, z, a, numargs() - 5);
- new
- n = numargs(),
- w = 5,
- s,
- weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
- cw;
- _CLASS_WEAPON_CODE
- return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, Group:-1, Group:-1);
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="forgroup">Group that can use the skin.</param>
- * <param name="setgroup">Group to add the player to on selection.</param>
- * <param name="skin">Skin of the class.</param>
- * <param name="x">X spawn location.</param>
- * <param name="y">Y spawn location.</param>
- * <param name="z">Z spawn location.</param>
- * <param name="a">A spawn location.</param>
- * <param name="">Spawn weapons and ammo (weapon then ammo)</param>
- * <remarks>
- * Pretty much AddPlayerClass but allows greater control over the classes.
- * Now has infinate (MAX_CLASS_SPAWN_WEAPONS) spawn weapons.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- stock Class_AddEx(Group:forgroup, Group:setgroup, skin, Float:x, Float:y, Float:z, Float:a, ...)
- {
- P:3("Class_AddEx called: %i, %i, %i, %f, %f, %f, %f (+%i)", _:forgroup, _:setgroup, skin, x, y, z, a, numargs() - 7);
- new
- n = numargs(),
- w = 7,
- s,
- weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
- cw;
- _CLASS_WEAPON_CODE
- return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, forgroup, setgroup);
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="group">Group to allow to use the class.</param>
- * <param name="skin">Skin of the class.</param>
- * <param name="x">X spawn location.</param>
- * <param name="y">Y spawn location.</param>
- * <param name="z">Z spawn location.</param>
- * <param name="a">A spawn location.</param>
- * <param name="">Weapon data.</param>
- * <remarks>
- * Adds a class only people in the specified group can use.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- stock Class_AddForGroup(Group:group, skin, Float:x, Float:y, Float:z, Float:a, ...)
- {
- P:3("Class_AddForGroup called: %i, %i, %f, %f, %f, %f (+%i)", _:group, skin, x, y, z, a, numargs() - 6);
- new
- n = numargs(),
- w = 6,
- s,
- weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
- cw;
- _CLASS_WEAPON_CODE
- return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, group, Group:-1);
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="group">Group to make players who use this group.</param>
- * <param name="skin">Skin of the class.</param>
- * <param name="x">X spawn location.</param>
- * <param name="y">Y spawn location.</param>
- * <param name="z">Z spawn location.</param>
- * <param name="a">A spawn location.</param>
- * <param name="">Spawn weapons.</param>
- * <remarks>
- * Adds a class which puts you in the specified group when selected.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- stock Class_AddWithGroupSet(Group:group, skin, Float:x, Float:y, Float:z, Float:a, ...)
- {
- P:3("Class_AddWithGroupSet called: %i, %i, %f, %f, %f, %f (+%i)", _:group, skin, x, y, z, a, numargs() - 6);
- new
- n = numargs(),
- w = 6,
- s,
- weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
- cw;
- _CLASS_WEAPON_CODE
- return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, Group:-1, group);
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="skin">Skin of the class.</param>
- * <param name="x">X spawn location.</param>
- * <param name="y">Y spawn location.</param>
- * <param name="z">Z spawn location.</param>
- * <param name="a">A spawn location.</param>
- * <param name="weapons">Array of spawn weapon data.</param>
- * <param name="count">Number of weapons added.</param>
- * <param name="forgroup">Group that can use the class.</param>
- * <param name="asgroup">Group to assign people to with this class.</param>
- * <remarks>
- * Does the hard work. This took a long time to get working correctly with the
- * new master system, infact getting just this one function to compile took a
- * major re-working of the macros to reduce the length of intermediate stages.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- foreign Class_AddClass(s,Float:x,Float:y,Float:z,Float:a,w[],c,Group:f,Group:g);
- global Class_AddClass(s,Float:x,Float:y,Float:z,Float:a,w[],c,Group:f,Group:g)
- {
- #pragma unused c
- P:2("Class_AddClass called: %i, %f, %f, %f, %f, %s, %i, %i, %i", s, x, y, z, a, Debug_PrintArray(w, c), c, _:f, _:g);
- new
- i;
- while (i != MAX_CLASSES && _Class_IsActive(i)) ++i;
- if (i == MAX_CLASSES) return -1;
- YSI_g_sClasses[i][E_CLASS_FLAGS] = e_CLASS_FLAGS_ACTIVE | e_CLASS_FLAGS_ENABLED | e_CLASS_FLAGS:s,
- YSI_g_sClasses[i][E_CLASS_X] = x,
- YSI_g_sClasses[i][E_CLASS_Y] = y,
- YSI_g_sClasses[i][E_CLASS_Z] = z,
- YSI_g_sClasses[i][E_CLASS_A] = a,
- memcpy(YSI_g_sClasses[i][E_CLASS_WEAPONS], w, 0, (MAX_CLASS_SPAWN_WEAPONS + 1) * 4, MAX_CLASS_SPAWN_WEAPONS + 1);
- // P:7("Class_AddClass: weapon %d %d %d", j, c, i);
- PA_FastInit(YSI_g_sClasses[i][E_CLASS_PLAYERS]);
- // P:7("Class_AddClass: weapon %d %d %d", j, c, f);
- Class_ResolveGroups(i, f, false);
- // P:7("Class_AddClass: weapon %d %d %d", j, c, g);
- YSI_g_sClasses[i][E_CLASS_GROUP] = g;
- YSI_g_sClassCount++;
- // P:7("Class_AddClass: weapon %d %d %d", j, c, YSI_g_sClassCount);
- return i;
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">The class to test.</param>
- * <param name="group">The group to test setting of.</param>
- * <returns>
- * Does this class add players to the given group on spawn?
- * </returns>
- *//*------------------------------------------------------------------------**/
- foreign Class_HasGroup(classid, Group:group);
- global Class_HasGroup(classid, Group:group)
- {
- return YSI_g_sClasses[classid][E_CLASS_GROUP] == group;
- }
- /*-------------------------------------------------------------------------*//**
- *//*------------------------------------------------------------------------**/
- foreign Class_Enable(classid, bool:toggle);
- global Class_Enable(classid, bool:toggle)
- {
- if (_Class_IsValid(classid))
- {
- if (toggle)
- {
- YSI_g_sClasses[classid][E_CLASS_FLAGS] |= e_CLASS_FLAGS_ENABLED;
- }
- else
- {
- YSI_g_sClasses[classid][E_CLASS_FLAGS] &= ~e_CLASS_FLAGS_ENABLED;
- // Hide the class for anyone currently viewing it.
- foreach (new playerid : Player)
- {
- P:5("Class_Enable: %d %d %d", playerid, _:YSI_g_sPlayerClass[playerid], _:e_PLAYER_CLASS_IN_SELECTION);
- if (Player_InSelection(playerid))
- {
- _Class_OnPlayerRequestClass(playerid, YSI_g_sInternalClass[playerid]);
- }
- }
- }
- return 1;
- }
- return 0;
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to delete.</param>
- * <remarks>
- * Completely removes a class from the system.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- foreign void:Class_Delete(classid);
- global void:Class_Delete(classid)
- {
- P:2("Class_Delete called: %i", classid);
- if (Class_Enable(classid, false))
- {
- YSI_g_sClasses[classid][E_CLASS_FLAGS] = e_CLASS_FLAGS:0;
- }
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to set permissions for.</param>
- * <param name="playerid">Player to set for.</param>
- * <param name="set">Whether or not they can use this class.</param>
- *//*------------------------------------------------------------------------**/
- foreign void:Class_SetPlayer(cl, pid, bool:s);
- global void:Class_SetPlayer(cl, pid, bool:s)
- {
- PA_Set(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid, s);
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="classid">Class to set permissions for.</param>
- * <param name="playerid">Player to set for.</param>
- *//*------------------------------------------------------------------------**/
- foreign bool:Class_GetPlayer(cl,pid);
- global bool:Class_GetPlayer(cl,pid)
- {
- return PA_Get(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid);
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="playerid">Player to get the current class of.</param>
- *//*------------------------------------------------------------------------**/
- foreign Class_Get(playerid);
- global Class_Get(playerid)
- {
- if (VALID_PLAYERID(playerid))
- {
- return YSI_g_sPlayerClass[playerid];
- }
- return -1;
- }
- #if defined _ALS_AddPlayerClass
- #undef AddPlayerClass
- #else
- #define _ALS_AddPlayerClass
- #endif
- #define AddPlayerClass Class_Add
- /*-------------------------------------------------------------------------*//**
- * <param name="playerid">Player whose current class view may need to change.</param>
- * <remarks>
- * If you change a player's groups while they are in class selection, call this
- * function to potentially update the currently displayed class.
- * </remarks>
- *//*------------------------------------------------------------------------**/
- stock Class_Reprocess(playerid)
- {
- if (!Player_InSelection(playerid))
- return 0;
- new
- classid = -1;
- if (YSI_g_sClassCount)
- {
- // Find the next available skin for this player. I'm still not
- // sure how this handles the case where you can't use any skin.
- // I'll have to look in to that - don't want to get stuck
- // constantly adding "0".
- classid = Class_FindNew(playerid, YSI_g_sPlayerClass[playerid], 0),
- Class_Goto(playerid, classid);
- P:5("Class_Reprocess() selected: %d", classid);
- }
- else
- {
- P:E("No YSI classes found");
- SetSpawnInfo(playerid, NO_TEAM, 0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0),
- SetPlayerSkin(playerid, 0);
- }
- return CallRemoteFunction("Class_OnPlayerRequestClass", "ii", playerid, classid);
- }
- /*-------------------------------------------------------------------------*//**
- * <param name="playerid">Player who requested a class.</param>
- * <param name="class">Class they requested.</param>
- * <remarks>
- * The input is one of the three real classes used to detect selected
- * direction of alteration. Scans for a class the player is allowed to use
- * and hot swaps it out. Uses SetPlayerSkin AND SetSpawnInfo to combat bugs
- * with calling this from OnPlayerRequestSpawn (e.g. the example team script).
- * Calls OnPlayerRequestClassEx with the current internal class not the real
- * one.
- *
- * Last thing in the file to be simpler to call directly. If we ever have a
- * more complex ALS hook on this callback the main body of this code will have
- * to be moved in to its own function. As indeed it now does!
- * </remarks>
- *//*------------------------------------------------------------------------**/
- public OnPlayerRequestClass(playerid, classid)
- {
- return _Class_OnPlayerRequestClass(playerid, classid);
- }
- // Pre-empt y_hooks.
- #if !defined YSI_NO_MASTER && _YSIM_IS_CLIENT
- static stock _Class_OnPlayerRequestClass(playerid, classid)
- {
- #pragma unused playerid, classid
- return 1;
- }
- #else
- #if !defined YSI_NO_MASTER && _YSIM_IS_CLOUD
- static stock _Class_OnPlayerRequestClass(playerid, classid) <>
- {
- #pragma unused playerid, classid
- return 1;
- }
-
- static stock _Class_OnPlayerRequestClass(playerid, classid) <_YCM:y>
- #else
- static stock _Class_OnPlayerRequestClass(playerid, classid)
- #endif
- {
- P:1("Class_OnPlayerRequestClass called: %d %d", playerid, classid);
- // Find which direction they pressed.
- if (YSI_g_sClassCount)
- {
- // Find the next available skin for this player. I'm still not
- // sure how this handles the case where you can't use any skin.
- // I'll have to look in to that - don't want to get stuck
- // constantly adding "0".
- new
- cid = classid;
- classid = Class_FindNew(playerid, YSI_g_sPlayerClass[playerid], ((classid - YSI_g_sInternalClass[playerid]) + 1) % 3 - 1),
- YSI_g_sInternalClass[playerid] = cid,
- Class_Goto(playerid, classid);
- P:5("Class_OnPlayerRequestClass() selected: %d", classid);
- }
- else
- {
- P:E("No YSI classes found");
- SetSpawnInfo(playerid, NO_TEAM, 0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0),
- SetPlayerSkin(playerid, 0),
- classid = -1;
- }
- return CallRemoteFunction("Class_OnPlayerRequestClass", "ii", playerid, classid);
- }
- #endif
- // Use the special pre-y_hooks hook method.
- HOOK_FORWARD:Class_OnPlayerRequestClass(playerid, classid);
- #if defined _ALS_OnPlayerRequestClass
- #undef OnPlayerRequestClass
- #else
- #define _ALS_OnPlayerRequestClass
- #endif
- #define OnPlayerRequestClass(%0) Class_OnPlayerRequestClass(%0) <_ALS : _ALS_go>
|