|
Member
|

09-12-2010
, 22:06
Re: Player Animations
|
#15
|
Plugin Source / .sma
PHP Code:
#include <amxmodx> #include <amxmisc> #include <fakemeta> #include <hamsandwich> #include <cstrike>
#define PLUG_NAME "PlrAnims" #define PLUG_AUTH "SgtBane" #define PLUG_VERS "0.5" #define PLUG_TAG "PlrAnims"
#define offset_nextanim 1000 #define menusize 220
#define PLUG_ACCESS ADMIN_CHAT
//stock fm_set_entity_visibility(index, invisible = 0) set_pev(index, pev_effects, invisible == 0 ? pev(index, pev_effects) & ~EF_NODRAW : pev(index, pev_effects) | EF_NODRAW)
new AnimFile[41] new AnimConfig[64]
new g_Animed[33] new g_Avatar[33] new g_Anim[33]
new p_MoveHead, p_LockRot, p_adminonly
#define anim_None -1
#define MaxAnims 32 new AnimCnt new saycmds[MaxAnims][31] new saysentence[MaxAnims][31] new Float:playlength[MaxAnims] new Float:playframerate[MaxAnims] new nextsequencenumb[MaxAnims]
public plugin_init() { register_plugin(PLUG_NAME, PLUG_VERS, PLUG_AUTH) RegisterHam(Ham_Spawn, "player", "fwd_playerspawn", 1) RegisterHam(Ham_TakeDamage, "player", "fwd_TakeDamage") register_forward(FM_CmdStart, "fwd_cmdstart") register_event("CurWeapon", "fwd_curweapon", "be", "1=1") register_clcmd("say", "hook_say") register_concmd("amx_anim_reloadini", "func_reloadini", ADMIN_RCON, "ReLoads the .ini file") p_MoveHead = register_cvar("amx_anim_movehead", "1") p_LockRot = register_cvar("amx_anim_lockrot", "1") p_adminonly = register_cvar("amx_anim_admin", "1") } public func_reloadini(id,level,cid) { if (!cmd_access(id,level,cid,1)) return PLUGIN_HANDLED command_load() return PLUGIN_HANDLED } public hook_say(id) { new said[21], match[22] read_args(said, 20) remove_quotes(said) if (get_pcvar_num(p_adminonly) == 1 && !(get_user_flags(id) & PLUG_ACCESS)) return PLUGIN_CONTINUE if (!is_user_alive(id)) return PLUGIN_CONTINUE for (new i=0; i<AnimCnt; i++) { format(match, 21, "/%s", saycmds[i]) if (equali(said, match)) { g_Animed[id] = i ToggleAnim(id, true) //client_print(id, print_center, "You are now %s", saysentence[i]) return PLUGIN_HANDLED } } return PLUGIN_CONTINUE }
public fwd_curweapon(id) { if(!is_user_alive(id)) return PLUGIN_CONTINUE if (g_Animed[id] == anim_None) return PLUGIN_CONTINUE if (read_data(2) != CSW_KNIFE) { //If they try to change to a weapon other than the knife, stop the animation. g_Animed[id] = anim_None ToggleAnim(id, false) } return PLUGIN_CONTINUE } public fwd_TakeDamage(Victim, Useless, Attacker, Float:damage, damagebits) { if (!is_user_connected(Victim)) return HAM_IGNORED if (g_Animed[Victim] == anim_None) return FMRES_IGNORED //If they are currently using an animation and get hurt, stop the animation. g_Animed[Victim] = anim_None ToggleAnim(Victim, false) return FMRES_IGNORED } public fwd_cmdstart(id, const uc_handle, random_seed) { if (!is_user_alive(id)) return FMRES_IGNORED if (g_Animed[id] == anim_None) return FMRES_IGNORED static buttons buttons = get_uc(uc_handle, UC_Buttons)
if (buttons & IN_FORWARD || buttons & IN_MOVELEFT || buttons & IN_MOVERIGHT || buttons & IN_BACK || buttons & IN_ATTACK || buttons & IN_ATTACK2 || buttons & IN_DUCK || buttons & IN_JUMP || buttons & IN_USE) { g_Animed[id] = anim_None ToggleAnim(id, false) return FMRES_IGNORED } new Float:fTest get_uc(uc_handle, UC_SideMove, fTest) if (fTest != 0.0) { g_Animed[id] = anim_None ToggleAnim(id, false) return FMRES_IGNORED } get_uc(uc_handle, UC_ForwardMove, fTest) if (fTest != 0.0) { g_Animed[id] = anim_None ToggleAnim(id, false) return FMRES_IGNORED } get_uc(uc_handle, UC_UpMove, fTest) if (fTest != 0.0) { g_Animed[id] = anim_None ToggleAnim(id, false) return FMRES_IGNORED } if (get_pcvar_num(p_MoveHead) != 0) { static Float:fAngA[3], Float:fAngB[3] pev(g_Anim[id], pev_angles, fAngA) pev(id, pev_v_angle, fAngB) fAngA[0] = (fAngB[0] - fAngA[0]) fAngA[0] + ((fAngA[0]) / 90.0 * 255.0) fAngA[0] += 90.0 fAngA[1] = (fAngB[1] - fAngA[1]) + 180 if(fAngA[1]>=360.0) fAngA[1] -= 360.0 if(fAngA[1]<0.0) fAngA[1] += 360.0
fAngA[1] = ((fAngA[1]) / 360.0 * 255.0) if (get_pcvar_num(p_LockRot) != 0) { if (fAngA[1] > 191.25 && fAngA[1] < 255.0) fAngA[1] = 191.25 if (fAngA[1] < 63.75 && fAngA[1] >= 0) fAngA[1] = 63.75 } //client_print(id, print_center, "Pitch:%i Yaw:%i", floatround(fAngA[0]), floatround(fAngA[1])) set_pev(g_Anim[id], pev_controller_1, floatround(fAngA[0])) set_pev(g_Anim[id], pev_controller_0, floatround(fAngA[1])) } return FMRES_IGNORED }
public fwd_playerspawn(id) { if (!is_user_alive(id)) return if (get_user_team(id) != 1 && get_user_team(id) != 2) return if (!pev_valid(g_Avatar[id])) { g_Avatar[id] = fm_find_ent_by_owner(0, "Anim_Avatar", id) if (pev_valid(g_Avatar[id])) { server_print("[%s]Recycling Avatar:%i for %i", PLUG_TAG, g_Avatar[id], id) } else { g_Avatar[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target")) server_print("[%s]Created Avatar:%i for %i", PLUG_TAG, g_Avatar[id], id) } if (pev_valid(g_Avatar[id])) { set_pev(g_Avatar[id], pev_classname, "Anim_Avatar") set_pev(g_Avatar[id], pev_owner, id) set_pev(g_Avatar[id], pev_movetype, MOVETYPE_FOLLOW) set_pev(g_Avatar[id], pev_solid, 0) MakeInvisible(g_Avatar[id], 1) } } if (!pev_valid(g_Anim[id])) { g_Anim[id] = fm_find_ent_by_owner(0, "Anim_Struct", id) if (pev_valid(g_Anim[id])) { server_print("[%s]Recycling Anim Structure:%i for %i", PLUG_TAG, g_Anim[id], id) } else { g_Anim[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target")) server_print("[%s]Created Anim Structure:%i for %i", PLUG_TAG, g_Anim[id], id) } if (pev_valid(g_Anim[id])) { set_pev(g_Anim[id], pev_classname, "Anim_Struct") set_pev(g_Anim[id], pev_owner, id) set_pev(g_Anim[id], pev_movetype, MOVETYPE_TOSS)
engfunc(EngFunc_SetModel, g_Anim[id], AnimFile) engfunc(EngFunc_SetSize, g_Anim[id], {-16.0, -16.0, 0.0}, {16.0, 16.0, 72.0}) set_pev(g_Anim[id], pev_solid, SOLID_BBOX) MakeInvisible(g_Anim[id], 1) } } if (pev_valid(g_Avatar[id]) && is_user_alive(id)) { if (task_exists(id)) remove_task(id) set_task(1.0, "delayedmdlset", id) } g_Animed[id] = anim_None ToggleAnim(id, false) } public delayedmdlset(id) { // Delaying because custom models don't get set till shortly after spawn. if (!is_user_alive(id)) return if (!pev_valid(g_Avatar[id])) return new modelname[41] cs_get_user_model (id, modelname, 40) format(modelname, 40, "models/player/%s/%s.mdl", modelname, modelname) engfunc(EngFunc_SetModel, g_Avatar[id], modelname) return } public plugin_precache() { new cfgDir[32] get_configsdir(cfgDir,31) formatex(AnimConfig,63,"%s/AnimConfig.ini",cfgDir) command_load() precache_model(AnimFile) } public ToggleAnim(id, bool:TogAnim) { if (pev_valid(g_Avatar[id]) && pev_valid(g_Anim[id])) { if (TogAnim && is_user_alive(id)) { MakeInvisible(g_Anim[id], 0) MakeInvisible(g_Avatar[id], 0) MakeInvisible(id, 1) new Float:fOrigin[3], Float:fAngles[3], Float:fVelocity[3] pev(id, pev_origin, fOrigin) fOrigin[2] -= 36.0 set_pev(g_Anim[id], pev_origin, fOrigin) pev(id, pev_angles, fAngles) fAngles[0] = 0.0 fAngles[2] = 0.0 set_pev(g_Anim[id], pev_angles, fAngles) pev(id, pev_velocity, fVelocity) set_pev(g_Anim[id], pev_velocity, fVelocity) //falltofloor(g_Anim[id]) set_pev(g_Avatar[id], pev_aiment, g_Anim[id]) set_pev(g_Anim[id], pev_framerate, playframerate[g_Animed[id]]) set_pev(g_Anim[id], pev_sequence, g_Animed[id]) set_pev(g_Anim[id], pev_frame, 0) set_pev(g_Anim[id], pev_animtime, get_gametime()) engclient_cmd(id, "weapon_knife") if (nextsequencenumb[g_Animed[id]] > anim_None && playlength[g_Animed[id]] > anim_None) { if (task_exists(offset_nextanim + id)) remove_task(offset_nextanim + id) set_task(playlength[g_Animed[id]], "task_nextanim", offset_nextanim + id) } //client_print(id, print_chat, "%i %s %s %i %i", g_Animed[id], saycmds[g_Animed[id]], saysentence[g_Animed[id]], floatround(playlength[g_Animed[id]]), str_to_num(nextsequencenumb[g_Animed[id]])) } else { MakeInvisible(g_Anim[id], 1) MakeInvisible(g_Avatar[id], 1) MakeInvisible(id, 0) set_pev(g_Avatar[id], pev_aiment, id) set_pev(g_Anim[id], pev_sequence, 0) if (task_exists(offset_nextanim + id)) remove_task(offset_nextanim + id) } } else { new name[32] get_user_name(id, name, 31) server_print("[%s]Error: %i%s Tried to run an animation with Avatar:%s Anim:%s", PLUG_TAG, id, name, pev_valid(g_Avatar[id])?"Valid":"Invalid", pev_valid(g_Anim[id])?"Valid":"Invalid") } } public task_nextanim(id) { id -= offset_nextanim g_Animed[id] = nextsequencenumb[g_Animed[id]] if (g_Animed[id] >= 0) { ToggleAnim(id, true) } }
//24.200.185.50:27015 stock MakeInvisible(id, invisible = 1) { set_pev(id, pev_effects, invisible == 0 ? pev(id, pev_effects) & ~EF_NODRAW : pev(id, pev_effects) | EF_NODRAW) } stock falltofloor(ent) { new Float:fOriginA[3], Float:fOriginB[3], Float:fHit[3] pev(ent, pev_origin, fOriginA) pev(ent, pev_origin, fOriginB) fOriginB[2] -= 64 fm_trace_line(ent, fOriginA, fOriginB, fHit) set_pev(ent, pev_velocity, {0.0, 0.0, 10.0}) //Force the game to update its position set_pev(ent, pev_origin, fHit) } stock fm_trace_line(ignoreent, const Float:start[3], const Float:end[3], Float:ret[3]) { engfunc(EngFunc_TraceLine, start, end, ignoreent == -1 ? 1 : 0, ignoreent, 0) get_tr2(0, TR_vecEndPos, ret) } stock fm_find_ent_by_owner(index, const classname[], owner) { new ent = index while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) && pev(ent, pev_owner) != owner) {} return ent }
public command_load() { new tmpCmd[31], tmpSent[31], tmpLen[5], tmpNext[4], tmpRate[7] if(file_exists(AnimConfig)) { AnimCnt = 0 new sfLineData[128] new file = fopen(AnimConfig,"rt") while(file && !feof(file)) { fgets(file,sfLineData,127) // Skip Comment ; // and Empty Lines if (sfLineData[0] == ';' || strlen(sfLineData) < 1 || (sfLineData[0] == '/')) continue if (containi(sfLineData, "Model=") > -1) { new strGarb[26] parse(sfLineData, strGarb, 25, AnimFile, 40) } else { // BREAK IT UP! parse(sfLineData, tmpCmd, 30, tmpSent, 30, tmpRate, 6, tmpLen, 4, tmpNext, 3) saycmds[AnimCnt] = tmpCmd saysentence[AnimCnt] = tmpSent playlength[AnimCnt] = str_to_float(tmpLen) playframerate[AnimCnt] = str_to_float(tmpRate) if (tmpNext[0] == '-') { nextsequencenumb[AnimCnt] = -1 } else { nextsequencenumb[AnimCnt] = str_to_num(tmpNext) } AnimCnt += 1 if(AnimCnt >= MaxAnims) { server_print("[%s] Reached animation limit",PLUG_TAG) break } } } if(file) fclose(file) } }
Create file named "AnimConfig.ini" and place in your configs folder. Put the following text in it.
Code:
model= "models/Anim/playeranimha.mdl"
/Command Sentence FrameRate Length Next
"Stand" "Stand" 1.0 0.0 -0
"Sit" "Sitting" 1.0 0.0 -0
"Sit2" "Sitting" 1.0 0.0 -0
"Wave" "Waving" 1.5 0.0 -0
"Float" "Floating" 1.0 0.0 -0
"Finger" "Giving the Finger" 1.0 1.0 0
"Scratch" "Scratching" 0.8 1.0 0
"Pump" "Fist Pumping" 1.0 0.0 -0
"Flip" "Flipping" 1.0 1.0 0
"Lay" "Laying" 1.0 0.0 -0
"Pushup" "Doing Pushups" 1.0 0.0 -0
"Pound" "Chest Pounding" 0.75 0.0 -0
"Y" "The Y" 1.0 0.0 -0
"M" "The M" 1.0 0.0 -0
"C" "The C" 1.0 0.0 -0
"A" "The A" 1.0 0.0 -0
"DanceA" "Dancing" 0.5 0.0 -0
"DanceB" "Dancing" 1.0 0.0 -0
"Beatit" "MJ Beat It" 1.8 0.0 -1
Add the attached model:
"models/Anim/playeranimha.mdl"
Sorry, I haven't checked these forums in a while, Always dipping in and out of playing CS. That is as far as I got with this, feel free to do whatever you want with it. If I missed something let me know.
Above code has the head movement part, and stops the animation when shot, or the player tries to move.
Still defiantly not something ready to just release on a server yet, but I tried to make it user friendly
say /"command" to use an animation.
Example say /sit, /sit2, /wave
If you make any changes to the .ini and you want the plugin to reload it without changing maps, use:
amx_anim_reloadini
Cvar, Default - Description
amx_anim_movehead, 1 - Allow heads to move where the player is looking when 'animating'
amx_anim_lockrot, 1 - Lock head movement to 180 degrees. (if set to 0, it looks kinda creepy)
amx_anim_admin, 1 - Only allow admins to use the animations
and to clear something up, some people don't seem to get it exactly..
There is one custom model needed to be downloaded from the server. It needed to have vertexes attached to it or the compiler would ignores the bones, but it is a very low poly model, and it ends up makes it a little easier to work with when animating. Besides that, all of the sequences are inside the single model. Its a very small download (76kb, less than the size of most Hat models)
__________________
Last edited by sgtbane; 02-04-2011 at 00:19.
|
|