/********************************여러 플러그인에서 공통적으로 쓰일 수 있는 유용한 함수**************************/ #if defined _javaliastocklib_included #endinput #endif #define _javaliastocklib_included #define _STOCKLIB_VERSION 1.0 /* let me say about this stocklib on here. well....as u see, all kinds of functions that i have been made for my plugins but i didnt able to make some nice include file name to put em r on here. u can find some defines from source engine, functions related to effect/damage/usermsg and more pointless things. in example, there is endround function for css, but u know, now there is super nice round end function on SM in default. so lets just use SM`s one. i didnt even marked deprecated functions perfectly, so some deprecated functions will keep stay on this include file. wut i am hoping by using this file on my plugin and releasing it is just helping myself`s lazy coding and i found sometimes this was helped some people. and well...this is not only one stock set, see the SMlib, its more good in any mean. except the makeExplosion function and makeDamage2 and makeDamage for now(2012 2 3) but they maybe can add/improve function at any time. even sdkhooks has good takedamage function. but remember, there is at least 1 or more way to do something. same for sm scripting. even it will sometimes seems retarded that many guys r making function to do same thing in different ways.. it has some mean. bye, thanks for reading this and looking my inc file. regardless is this file good or bad, it is one of most adorable/moeful result of my work/hobby. i hope u can find some useful thing for u on here. */ //this define can used with valve games only. like tf2, hl2mp, css, dods ect #define TEAM_UNASSIGNED 0 #define TEAM_SPECTATOR 1 #define TEAM_RED 2 #define TEAM_BLUE 3 #define TEAM_TYPE_FIRST 0 #define TEAM_TYPE_MAX 4 //how many teams are exist? in this case, 4 team is exist // m_lifeState values #define LIFE_ALIVE 0 // alive #define LIFE_DYING 1 // playing death animation or still falling off of a ledge waiting to hit ground #define LIFE_DEAD 2 // dead. lying still. #define LIFE_RESPAWNABLE 3 #define LIFE_DISCARDBODY 4 //env_beam 의 터치타입 enum Touch_t{ touch_none = 0, touch_player_only, touch_npc_only, touch_player_or_npc, touch_player_npc_physicsprop, }; //print to server in server`s language`s translation //this function is designed to save your finger against code like this //PrintToServer("%T%T%T", "smeffectitemshop:", LANG_SERVER, "attemp", LANG_SERVER, "main db connect", LANG_SERVER); //deprecated, useless, dont use, i will delete it whenever i delete this function from whole of my codes.herp. stock PrintToServerT(const String:format[], any:...){ decl String:txt[1024]; SetGlobalTransTarget(LANG_SERVER); VFormat(txt, sizeof(txt), format, 2); PrintToServer(txt); } //deprecated, useless, dont use, i will delete it whenever i delete this function from whole of my codes.derp. stock LogErrorT(const String:format[], any:...){ decl String:txt[1024]; SetGlobalTransTarget(LANG_SERVER); VFormat(txt, sizeof(txt), format, 2); LogError(txt); } //deprecated, useless, dont use, i will delete it whenever i delete this function from whole of my codes.derp. stock bool:isClientConnectedIngameAlive(client){ if(isClientConnectedIngame(client)){ if(IsPlayerAlive(client) == true && IsClientObserver(client) == false){ return true; }else{ return false; } }else{ return false; } } //클라이언트 상태 체크 2개를 한꺼번에 해주는 함수 //클라이언트가 게임 안에 있는지까지 검사한다. stock bool:isClientConnectedIngame(client){ if(client > 0 && client <= MaxClients){ if(IsClientInGame(client) == true){ return true; }else{ return false; } }else{ return false; } } //클라이언트가 3인칭 시점으로 보게 해 주는 함수 stock bool:activeThirdPerson(client){ if(isClientConnectedIngameAlive(client)){ SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", 0); SetEntProp(client, Prop_Send, "m_iObserverMode", 1); SetEntProp(client, Prop_Send, "m_bDrawViewmodel", 0); return true; }else{ return false; } } //클라이언트가 1인칭 시점으로 보게 해 주는 함수 stock bool:activeFirstPerson(client){ if(isClientConnectedIngameAlive(client)){ SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", -1); SetEntProp(client, Prop_Send, "m_iObserverMode", 0); SetEntProp(client, Prop_Send, "m_bDrawViewmodel", 1); return true; }else{ return false; } } //damagetype #define DMG_GENERIC 0 // generic damage was done #define DMG_CRUSH (1 << 0) // crushed by falling or moving object. // NOTE: It's assumed crush damage is occurring as a result of physics collision, so no extra physics force is generated by crush damage. // DON'T use DMG_CRUSH when damaging entities unless it's the result of a physics collision. You probably want DMG_CLUB instead. #define DMG_BULLET (1 << 1) // shot #define DMG_SLASH (1 << 2) // cut, clawed, stabbed #define DMG_BURN (1 << 3) // heat burned #define DMG_VEHICLE (1 << 4) // hit by a vehicle #define DMG_FALL (1 << 5) // fell too far #define DMG_BLAST (1 << 6) // explosive blast damage #define DMG_CLUB (1 << 7) // crowbar, punch, headbutt #define DMG_SHOCK (1 << 8) // electric shock #define DMG_SONIC (1 << 9) // sound pulse shockwave #define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam #define DMG_PREVENT_PHYSICS_FORCE (1 << 11) // Prevent a physics force #define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death #define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death. #define DMG_DROWN (1 << 14) // Drowning #define DMG_PARALYZE (1 << 15) // slows affected creature down #define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad #define DMG_POISON (1 << 17) // blood poisoning - heals over time like drowning damage #define DMG_RADIATION (1 << 18) // radiation exposure #define DMG_DROWNRECOVER (1 << 19) // drowning recovery #define DMG_ACID (1 << 20) // toxic chemicals or acid burns #define DMG_SLOWBURN (1 << 21) // in an oven #define DMG_REMOVENORAGDOLL (1 << 22) // with this bit OR'd in, no ragdoll will be created, and the target will be quietly removed. // use this to kill an entity that you've already got a server-side ragdoll for #define DMG_PHYSGUN (1 << 23) // Hit by manipulator. Usually doesn't do any damage. #define DMG_PLASMA (1 << 24) // Shot by Cremator #define DMG_AIRBOAT (1 << 25) // Hit by the airboat's gun #define DMG_DISSOLVE (1 << 26) // Dissolving! #define DMG_BLAST_SURFACE (1 << 27) // A blast on the surface of water that cannot harm things underwater #define DMG_DIRECT (1 << 28) #define DMG_BUCKSHOT (1 << 29) // not quite a bullet. Little, rounder, different. stock bool:makeDamage(attacker, target, Float:damage, damagetype, Float:damageradius, const Float:attackposition[3], const String:weaponname[] = ""){ new pointhurt = CreateEntityByName("point_hurt"); if(pointhurt != -1){ //목표가 있을 경우 목표 입력, 목표가 없을 경우 범위 공격을 하게된다 if(target != -1){ decl String:targetname[64]; Format(targetname, 128, "%d", EntIndexToEntRef(target)); DispatchKeyValue(target,"TargetName", targetname); DispatchKeyValue(pointhurt,"DamageTarget", targetname); } //포인트허트 위치 지정 DispatchKeyValueVector(pointhurt, "Origin", attackposition); //데미지 지정 DispatchKeyValueFloat(pointhurt,"Damage", damage); //데미지타입 지정 decl String:number[64]; IntToString(damagetype, number, 64); DispatchKeyValue(pointhurt,"DamageType", number); //데미지 범위 지정 DispatchKeyValueFloat(pointhurt, "DamageRadius", damageradius); //웨폰네임 오버라이드 if(!StrEqual(weaponname, "", false)){ DispatchKeyValue(pointhurt,"classname", weaponname); } DispatchSpawn(pointhurt); AcceptEntityInput(pointhurt, "Hurt", attacker != -1 ? attacker : 0); AcceptEntityInput(pointhurt, "Kill"); return true; }else{ return false; } } /* * set damageduration to smaller than 0.0 to make it do damage forever until this entity is killed by other reason * set damageduration to 0.0 to make it damage once. * set customdamage to true will make point_hurt entity to not do any damage, so u should work with it yourself. * setting customdamage to true will ignore autoremove * be sure to set autoremove to false if u dont want to remove point_hurt entity automatically * * damageduration 을 0 으로 설정하면 데미지를 한번만 준다. 0보다 크게 하면 주어진 시간동안 데미지를 준다. * 0보다 작게 하면 포인트허트 엔티티가 사라지기 전까지 계속 데미지를 준다 * customdamage 를 true 로 설정하면 엔티티는 데미지를 주지 않는다. 직접 데미지를 주게 해야 한다. * 그리고 customdamage가 true라면 autoremove 인수는 무시된다. * 포인트허트 엔티티가 자동으로 사라지게 하고 싶지 않다면 autoremove 를 false로 설정하라 */ stock makeDamage2(attacker, target, damage, damagetype, Float:damageradius, Float:damagedelay, Float:damageduration, const Float:attackposition[3], const String:weaponname[] = "", bool:customdamage = false, bool:autoremove = true){ new pointhurt = CreateEntityByName("point_hurt"); if(pointhurt != -1){ //목표가 있을 경우 목표 입력, 목표가 없을 경우 범위 공격을 하게된다 if(target != -1){ decl String:targetname[64]; Format(targetname, 128, "%f%f", GetEngineTime(), GetRandomFloat()); DispatchKeyValue(target,"TargetName", targetname); DispatchKeyValue(pointhurt,"DamageTarget", targetname); } //포인트허트 위치 지정 DispatchKeyValueVector(pointhurt, "Origin", attackposition); //데미지 지정 decl String:number[64]; IntToString(damage, number, 64); DispatchKeyValue(pointhurt,"Damage", number); //데미지타입 지정 IntToString(damagetype, number, 64); DispatchKeyValue(pointhurt,"DamageType", number); //데미지 범위 지정 DispatchKeyValueFloat(pointhurt, "DamageRadius", damageradius); DispatchKeyValueFloat(pointhurt, "DamageDelay", damagedelay); //웨폰네임 오버라이드 if(!StrEqual(weaponname, "", false)){ DispatchKeyValue(pointhurt,"classname", weaponname); } DispatchSpawn(pointhurt); if(!customdamage){ if(damageduration == 0.0){ AcceptEntityInput(pointhurt, "Hurt", attacker != -1 ? attacker : 0); }else{ AcceptEntityInput(pointhurt, "TurnOn", attacker != -1 ? attacker : 0); } } if(autoremove){ if(!customdamage){ if(damageduration == 0.0){ AcceptEntityInput(pointhurt, "Kill"); }else if(damageduration > 0.0){ decl String:output[256]; Format(output, 256, "OnUser1 !self:kill:justkill:%.1f:1", damageduration); SetVariantString(output); AcceptEntityInput(pointhurt, "AddOutput"); AcceptEntityInput(pointhurt, "FireUser1"); } } }else{ if(!customdamage){ if(damageduration > 0.0){ decl String:output[256]; Format(output, 256, "OnUser1 !self:TurnOff:justTurnOff:%.1f:1", damageduration); SetVariantString(output); AcceptEntityInput(pointhurt, "AddOutput"); AcceptEntityInput(pointhurt, "FireUser1"); } } } return pointhurt; }else{ return -1; } } #define SF_ENVEXPLOSION_NODAMAGE 0x00000001 // when set, ENV_EXPLOSION will not actually inflict damage #define SF_ENVEXPLOSION_REPEATABLE 0x00000002 // can this entity be refired? #define SF_ENVEXPLOSION_NOFIREBALL 0x00000004 // don't draw the fireball #define SF_ENVEXPLOSION_NOSMOKE 0x00000008 // don't draw the smoke #define SF_ENVEXPLOSION_NODECAL 0x00000010 // don't make a scorch mark #define SF_ENVEXPLOSION_NOSPARKS 0x00000020 // don't make sparks #define SF_ENVEXPLOSION_NOSOUND 0x00000040 // don't play explosion sound. #define SF_ENVEXPLOSION_RND_ORIENT 0x00000080 // randomly oriented sprites #define SF_ENVEXPLOSION_NOFIREBALLSMOKE 0x0100 #define SF_ENVEXPLOSION_NOPARTICLES 0x00000200 #define SF_ENVEXPLOSION_NODLIGHTS 0x00000400 #define SF_ENVEXPLOSION_NOCLAMPMIN 0x00000800 // don't clamp the minimum size of the fireball sprite #define SF_ENVEXPLOSION_NOCLAMPMAX 0x00001000 // don't clamp the maximum size of the fireball sprite #define SF_ENVEXPLOSION_SURFACEONLY 0x00002000 // don't damage the player if he's underwater. #define SF_ENVEXPLOSION_GENERIC_DAMAGE 0x00004000 // don't do BLAST damage /* * if u set weaponname and inflictor, to accept weaponname correctly, this function will change classname of inflictor to weaponname * note : i dunno why but setting world as inflictor and changing weaponname caused problem. * * if u set any custom damage type, SF_ENVEXPLOSION_GENERIC_DAMAGE flag will be ignored even u set it. * if u not set custom damage type, SF_ENVEXPLOSION_GENERIC_DAMAGE flag will make damage type to DMG_GENERIC * if u didnt set both of custom damage type and SF_ENVEXPLOSION_GENERIC_DAMAGE, damage type will be DMG_BLAST * however, if u set SF_ENVEXPLOSION_SURFACEONLY flag, DMG_BLAST_SURFACE will be added on damage type * * ignoreentity is entity`s index that will not take dmg from this explosion. * ignoreclass is class`s index that will not take dmg from this explosion(will work with only few games). * team is team that this explosion will belongs to.(it will not give dmg to that team when friendly fire is off and like that...) * i putted team parameter on last because this parameter`s effect is a kind of side effect of source engine`s code * it`s return value will -1 if it fails to create explosion entity, and it will return ent index of explosion on success * but remember, unless u gave SF_ENVEXPLOSION_REPEATABLE flag, returned ent index will not valid to use again. * it will only mean explosion has succeed */ stock makeExplosion(attacker = 0, inflictor = -1, const Float:attackposition[3], const String:weaponname[] = "", magnitude = 100, radiusoverride = 0, Float:damageforce = 0.0, flags = 0, customdamagetype = -1, ignoreentity = -1, ignoreclass = -1, team = -1){ new explosion = CreateEntityByName("env_explosion"); if(explosion != -1){ DispatchKeyValueVector(explosion, "Origin", attackposition); decl String:intbuffer[64]; IntToString(magnitude, intbuffer, 64); DispatchKeyValue(explosion,"iMagnitude", intbuffer); if(radiusoverride > 0){ IntToString(radiusoverride, intbuffer, 64); DispatchKeyValue(explosion,"iRadiusOverride", intbuffer); } if(damageforce > 0.0){ DispatchKeyValueFloat(explosion,"DamageForce", damageforce); } if(flags != 0){ IntToString(flags, intbuffer, 64); DispatchKeyValue(explosion,"spawnflags", intbuffer); } if(!StrEqual(weaponname, "", false)){ DispatchKeyValue(explosion,"classname", weaponname); if(inflictor != -1){ DispatchKeyValue(inflictor,"classname", weaponname); } } DispatchSpawn(explosion); if(attacker != -1){ SetEntPropEnt(explosion, Prop_Send, "m_hOwnerEntity", attacker); } if(inflictor != -1){ SetEntPropEnt(explosion, Prop_Data, "m_hInflictor", inflictor); } if(ignoreentity != -1){ SetEntPropEnt(explosion, Prop_Data, "m_hEntityIgnore", ignoreentity); } if(ignoreclass != -1){ SetEntProp(explosion, Prop_Data, "m_iClassIgnore", ignoreclass); } if(team != -1){ SetEntProp(explosion, Prop_Data, "m_iTeamNum", team); } AcceptEntityInput(explosion, "Explode"); if(~flags & SF_ENVEXPLOSION_REPEATABLE){ AcceptEntityInput(explosion, "Kill"); } return explosion; }else{ return -1; } } //페이드 유저메시지 함수의 상수 #define FFADE_IN 0x0001 // Just here so we don't pass 0 into the function #define FFADE_OUT 0x0002 // Fade out (not in) #define FFADE_MODULATE 0x0004 // Modulate (don't blend) #define FFADE_STAYOUT 0x0008 // ignores the duration, stays faded out until new ScreenFade message received #define FFADE_PURGE 0x0010 // Purges all other fades, replacing them with this one stock sendFadeMsg(client, duration, holdtime, fadeflag, r, g, b, a){ new Handle:fademsg; if (client == 0){ fademsg = StartMessageAll("Fade"); }else{ fademsg = StartMessageOne("Fade", client); } BfWriteShort(fademsg, duration); BfWriteShort(fademsg, holdtime); BfWriteShort(fademsg, fadeflag); BfWriteByte(fademsg, r); BfWriteByte(fademsg, g); BfWriteByte(fademsg, b); BfWriteByte(fademsg, a); EndMessage(); } //쉐이크 유저메시지 함수의 상수 enum ShakeCommand_t{ SHAKE_START = 0, // Starts the screen shake for all players within the radius. SHAKE_STOP, // Stops the screen shake for all players within the radius. SHAKE_AMPLITUDE, // Modifies the amplitude of an active screen shake for all players within the radius. SHAKE_FREQUENCY, // Modifies the frequency of an active screen shake for all players within the radius. SHAKE_START_RUMBLEONLY, // Starts a shake effect that only rumbles the controller, no screen effect. SHAKE_START_NORUMBLE, // Starts a shake that does NOT rumble the controller. }; stock sendShakeMsg(client, all:shakeflag, Float:amplitude, Float:frequency, Float:duration){ new Handle:shakemsg; if (client == 0){ shakemsg = StartMessageAll("Shake"); }else{ shakemsg = StartMessageOne("Shake", client); } BfWriteByte(shakemsg, shakeflag); BfWriteFloat(shakemsg, amplitude); BfWriteFloat(shakemsg, frequency); BfWriteFloat(shakemsg, duration); EndMessage(); } //호출 예제 sendHudMsg(client, 6, 0.04, 0.82, 255, 120, 0, 255, 255, 120, 0, 225, 1, 0.1, 1000.0, 10.0, 4.0, totalhud); stock sendHudMsg(client, channel, Float:x, Float:y, r1, g1, b1, a1, r2, g2, b2, a2, effect, Float:fadein, Float:fadeout, Float:holdtime, Float:fxtime, const String:msg[]){ new Handle:hudhandle = INVALID_HANDLE; if (client == 0){ hudhandle = StartMessageAll("HudMsg"); }else{ hudhandle = StartMessageOne("HudMsg", client); } if(hudhandle != INVALID_HANDLE){ BfWriteByte(hudhandle, channel); //channel BfWriteFloat(hudhandle, x); // x ( -1 = center ) BfWriteFloat(hudhandle, y); // y ( -1 = center ) // second color BfWriteByte(hudhandle, r1); //r1 BfWriteByte(hudhandle, g1); //g1 BfWriteByte(hudhandle, b1); //b1 BfWriteByte(hudhandle, a1); //a1 // transparent? // init color BfWriteByte(hudhandle, r2); //r2 BfWriteByte(hudhandle, g2); //g2 BfWriteByte(hudhandle, b2); //b2 BfWriteByte(hudhandle, a2); //a2 BfWriteByte(hudhandle, effect); //effect (0 is fade in/fade out; 1 is flickery credits; 2 is write out) BfWriteFloat(hudhandle, fadein); //fadeinTime (message fade in time - per character in effect 2) BfWriteFloat(hudhandle, fadeout); //fadeoutTime BfWriteFloat(hudhandle, holdtime); //holdtime BfWriteFloat(hudhandle, fxtime); //fxtime (effect type(2) used) BfWriteString(hudhandle, msg); //Message EndMessage(); } } //this made effect on css, but no effect at hl2mp stock sendKeyHintTextMsg(client, String:msg[], any:...){ new Handle:hudhandle = INVALID_HANDLE; if (client == 0){ hudhandle = StartMessageAll("KeyHintText"); }else{ hudhandle = StartMessageOne("KeyHintText", client); } new String:txt[255]; VFormat(txt, sizeof(txt), msg, 3); if (hudhandle != INVALID_HANDLE) { BfWriteByte(hudhandle, 1); BfWriteString(hudhandle, txt); EndMessage(); } } //it was same as PrintHintText, but it made differant effect at hl2mp, it can print short single line msg stock sendHintTextMsg(client, String:msg[], any:...){ new Handle:hudhandle = INVALID_HANDLE; if (client == 0){ hudhandle = StartMessageAll("HintText"); }else{ hudhandle = StartMessageOne("HintText", client); } new String:txt[255]; VFormat(txt, sizeof(txt), msg, 3); if (hudhandle != INVALID_HANDLE) { BfWriteByte(hudhandle, 1); BfWriteString(hudhandle, txt); EndMessage(); } } //this has no effect stock sendHudText(client, String:msg[], any:...){ new Handle:hudhandle = INVALID_HANDLE; if (client == 0){ hudhandle = StartMessageAll("HudText"); }else{ hudhandle = StartMessageOne("HudText", client); } new String:txt[255]; VFormat(txt, sizeof(txt), msg, 3); if (hudhandle != INVALID_HANDLE) { BfWriteString(hudhandle, txt); EndMessage(); } } //this is sam for some exist functions of sourcemod #define HUD_PRINTNOTIFY 1 #define HUD_PRINTCONSOLE 2 #define HUD_PRINTTALK 3 #define HUD_PRINTCENTER 4 stock sendTextMsg(client, msgtype, const String:msgname[], const String:msg1[] = "", const String:msg2[] = "", const String:msg3[] = "", const String:msg4[] = ""){ new Handle:hudhandle = INVALID_HANDLE; if (client == 0){ hudhandle = StartMessageAll("TextMsg"); }else{ hudhandle = StartMessageOne("TextMsg", client); } if(hudhandle != INVALID_HANDLE){ BfWriteByte(hudhandle, msgtype); BfWriteString(hudhandle, msgname); //Message BfWriteString(hudhandle, msg1); //Message BfWriteString(hudhandle, msg2); //Message BfWriteString(hudhandle, msg3); //Message BfWriteString(hudhandle, msg4); //Message EndMessage(); } } /*휴드와 소스모드 함수 매칭 *DIALOG_ASKCONNECT = DisplayAskConnectBox *다른 타입들 = CreateDialog(client, Handle:kv, DialogType:type); */ //not so useful stock SendTopLeftText(client, r, g, b, a, level, time, const String:text[], any:...){ new String:message[100]; SetGlobalTransTarget(client); VFormat(message, sizeof(message), text, 9); new Handle:kv = CreateKeyValues("Stuff", "title", message); KvSetColor(kv, "color", r, g, b, a); KvSetNum(kv, "level", level); KvSetNum(kv, "time", time); if(client == 0){ for(new i = 1; i <= MaxClients; i++){ if(isClientConnectedIngame(i)){ CreateDialog(i, kv, DialogType_Msg); } } }else if(isClientConnectedIngame(client)){ CreateDialog(client, kv, DialogType_Msg); } CloseHandle(kv); } //세이텍스트올 stock SayText2ToAll(client, const String:message[], any:...){ new Handle:buffer = INVALID_HANDLE; new String:txt[255]; for(new i = 1; i <= MaxClients; i++){ if(IsClientInGame(i)){ SetGlobalTransTarget(i); VFormat(txt, sizeof(txt), message, 3); buffer = StartMessageOne("SayText2", i); if (buffer != INVALID_HANDLE) { BfWriteByte(buffer, client); BfWriteByte(buffer, true); BfWriteString(buffer, txt); EndMessage(); buffer = INVALID_HANDLE; } } } } //세이텍스트투 stock SayText2To(client, target, const String:message[], any:...){ new Handle:buffer = StartMessageOne("SayText2", target); new String:txt[255]; SetGlobalTransTarget(target); VFormat(txt, sizeof(txt), message, 4); if (buffer != INVALID_HANDLE) { BfWriteByte(buffer, client); BfWriteByte(buffer, true); BfWriteString(buffer, txt); EndMessage(); } } stock SetClientButtons(client, buttons){ return SetEntProp(client, Prop_Data, "m_nButtons", buttons); } stock bool:getTraceResult(const Float:pos[3], const Float:angle[3], const Float:maxtracedistance, &resultent, Float:resultvecpos[3], Float:resultvecnormal[3], TraceEntityFilter:function, filter){ new Handle:traceresulthandle = INVALID_HANDLE; traceresulthandle = TR_TraceRayFilterEx(pos, angle, MASK_SOLID, RayType_Infinite, function, filter); if(TR_DidHit(traceresulthandle) == true){ decl Float:endpos[3]; TR_GetEndPosition(endpos, traceresulthandle); TR_GetPlaneNormal(traceresulthandle, resultvecnormal); resultent = TR_GetEntityIndex(traceresulthandle); //거리가 일정 이하일 경우 if((GetVectorDistance(pos, endpos) <= maxtracedistance) || maxtracedistance <= 0){ resultvecpos[0] = endpos[0]; resultvecpos[1] = endpos[1]; resultvecpos[2] = endpos[2]; CloseHandle(traceresulthandle); return true; }else{ decl Float:anglevector[3]; GetAngleVectors(angle, anglevector, NULL_VECTOR, NULL_VECTOR); NormalizeVector(anglevector, anglevector); ScaleVector(anglevector, maxtracedistance); AddVectors(pos, anglevector, resultvecpos); CloseHandle(traceresulthandle); return true; } } CloseHandle(traceresulthandle); return false; } //살아있는 클라이언트의 에임방향으로부터 일정 거리 떨어진 곳을 구해서 돌려준다 stock bool:getClientAimPosition(client, Float:maxtracedistance, Float:resultvecpos[3], Float:resultvecnormal[3], TraceEntityFilter:function, filter){ decl Float:cleyepos[3], Float:cleyeangle[3], Float:eyeanglevector[3]; GetClientEyePosition(client, cleyepos); GetClientEyeAngles(client, cleyeangle); new Handle:traceresulthandle = INVALID_HANDLE; traceresulthandle = TR_TraceRayFilterEx(cleyepos, cleyeangle, MASK_SOLID, RayType_Infinite, function, filter); if(TR_DidHit(traceresulthandle) == true){ decl Float:endpos[3]; TR_GetEndPosition(endpos, traceresulthandle); TR_GetPlaneNormal(traceresulthandle, resultvecnormal); //거리가 일정 이하일 경우 if((GetVectorDistance(cleyepos, endpos) <= maxtracedistance) || maxtracedistance <= 0){ resultvecpos[0] = endpos[0]; resultvecpos[1] = endpos[1]; resultvecpos[2] = endpos[2]; CloseHandle(traceresulthandle); return true; }else{ GetAngleVectors(cleyeangle, eyeanglevector, NULL_VECTOR, NULL_VECTOR); NormalizeVector(eyeanglevector, eyeanglevector); ScaleVector(eyeanglevector, maxtracedistance); AddVectors(cleyepos, eyeanglevector, resultvecpos); CloseHandle(traceresulthandle); return true; } } CloseHandle(traceresulthandle); return false; } stock GetClientAimEntity(client, &Float:distancetoentity){ decl Float:cleyepos[3], Float:cleyeangle[3]; GetClientEyePosition(client, cleyepos); GetClientEyeAngles(client, cleyeangle); new Handle:traceresulthandle = INVALID_HANDLE; traceresulthandle = TR_TraceRayFilterEx(cleyepos, cleyeangle, MASK_SOLID, RayType_Infinite, tracerayfilterdefault, client); if(TR_DidHit(traceresulthandle) == true){ decl Float:endpos[3]; TR_GetEndPosition(endpos, traceresulthandle); distancetoentity = GetVectorDistance(cleyepos, endpos); new entindextoreturn = TR_GetEntityIndex(traceresulthandle); CloseHandle(traceresulthandle); return entindextoreturn; } CloseHandle(traceresulthandle); return -1; } stock GetClientAimEntity2(client){ decl Float:temp; return GetClientAimEntity(client, temp); } stock GetClientAimEntity3(client, &Float:distancetoentity, Float:endpos[3]){ decl Float:cleyepos[3], Float:cleyeangle[3]; GetClientEyePosition(client, cleyepos); GetClientEyeAngles(client, cleyeangle); new Handle:traceresulthandle = INVALID_HANDLE; traceresulthandle = TR_TraceRayFilterEx(cleyepos, cleyeangle, MASK_SOLID, RayType_Infinite, tracerayfilterdefault, client); if(TR_DidHit(traceresulthandle) == true){ TR_GetEndPosition(endpos, traceresulthandle); //거리가 일정 이하일 경우 distancetoentity = GetVectorDistance(cleyepos, endpos); new entindextoreturn = TR_GetEntityIndex(traceresulthandle); CloseHandle(traceresulthandle); return entindextoreturn; } CloseHandle(traceresulthandle); return -1; } // settings for m_takedamage #define DAMAGE_NO 0 #define DAMAGE_EVENTS_ONLY 1 // Call damage functions, but don't modify health #define DAMAGE_YES 2 #define DAMAGE_AIM 3 stock setTakeDamage(entity, type){ SetEntProp(entity, Prop_Data, "m_takedamage", type); } //트레이스레이필터 public bool:tracerayfilterdefault(entity, mask, any:data){ if(entity != data){ return true; }else{ return false; } } public bool:tracerayfilteronlyone(entity, mask, any:data){ if(entity == data && mask & CONTENTS_HITBOX){ return true; }else{ return false; } } //트레이스레이필터로켓 public bool:tracerayfilterrocket(entity, mask, any:data){ //로켓을 쏜 사람이 아니고, 그 사람의 물건도 아닐때만 필터에 감지한다 new owner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");//닿은 물건의 주인을 구한다 if(entity != data && owner != data){ return true; }else{ return false; } } //트레이스레이필터, 플레이어는 감지하지 않는다 public bool:tracerayfilternoplayer(entity, mask, any:data){ if(!isClientConnectedIngameAlive(entity)){ return true; }else{ return false; } } //0번 엔티티만 감지한다 public bool:tracerayfilteronlyworld(entity, mask, any:data){ if(entity == 0){ return true; }else{ return false; } } stock bool:IsStrBool(const String:str[], bool:onlynumeric = true){ if(onlynumeric){ return StrEqual(str, "1", false) || StrEqual(str, "0", false); }else{ return StrEqual(str, "1", false) || StrEqual(str, "0", false) || StrEqual(str, "true", false) || StrEqual(str, "false", false); } } //엔티티가 충돌 가능한 물체인지를 검사한다! stock bool:IsEntityCollidable(entity, bool:includeplayer = true, bool:includehostage = true, bool:includeprojectile = true){ decl String:classname[64]; GetEdictClassname(entity, classname, 64); if((StrEqual(classname, "player", false) && includeplayer) || (StrEqual(classname, "hostage_entity", false) && includehostage) ||StrContains(classname, "physics", false) != -1 || StrContains(classname, "prop", false) != -1 || StrContains(classname, "door", false) != -1 || StrContains(classname, "weapon", false) != -1 || StrContains(classname, "break", false) != -1 || ((StrContains(classname, "projectile", false) != -1) && includeprojectile) || StrContains(classname, "brush", false) != -1 || StrContains(classname, "button", false) != -1 || StrContains(classname, "physbox", false) != -1 || StrContains(classname, "plat", false) != -1 || StrEqual(classname, "func_conveyor", false) || StrEqual(classname, "func_fish_pool", false) || StrEqual(classname, "func_guntarget", false) || StrEqual(classname, "func_lod", false) || StrEqual(classname, "func_monitor", false) || StrEqual(classname, "func_movelinear", false) || StrEqual(classname, "func_reflective_glass", false) || StrEqual(classname, "func_rotating", false) || StrEqual(classname, "func_tanktrain", false) || StrEqual(classname, "func_trackautochange", false) || StrEqual(classname, "func_trackchange", false) || StrEqual(classname, "func_tracktrain", false) || StrEqual(classname, "func_train", false) || StrEqual(classname, "func_traincontrols", false) || StrEqual(classname, "func_vehicleclip", false) || StrEqual(classname, "func_traincontrols", false) || StrEqual(classname, "func_water", false) || StrEqual(classname, "func_water_analog", false)){ return true; } return false; } stock makeviewpunch(client, Float:angle[3]){ decl Float:oldangle[3]; GetEntPropVector(client, Prop_Send, "m_vecPunchAngle", oldangle); oldangle[0] = oldangle[0] + angle[0]; oldangle[1] = oldangle[1] + angle[1]; oldangle[2] = oldangle[2] + angle[2]; SetEntPropVector(client, Prop_Send, "m_vecPunchAngle", oldangle); SetEntPropVector(client, Prop_Send, "m_vecPunchAngleVel", angle); } stock resetviewpunch(client){ new Float:angle[3] = {0.0, 0.0, 0.0}; SetEntPropVector(client, Prop_Send, "m_vecPunchAngle", angle); SetEntPropVector(client, Prop_Send, "m_vecPunchAngleVel", angle); } stock bool:sendRawAudioTo(client, target, const String:sSound[255], iVoicePitch = 100, Float:fVoiceMarkShowTime = 1.0){ if(!isClientConnectedIngame(client)){ return false; } //Peace-Maker has found how to use this usermsg, well, i helped him lol new Handle:buffer = StartMessageOne("RawAudio", target); if (buffer != INVALID_HANDLE){ BfWriteByte(buffer, iVoicePitch); BfWriteByte(buffer, client); BfWriteFloat(buffer, fVoiceMarkShowTime); BfWriteString(buffer, sSound); EndMessage(); return true; } return false; } stock bool:sendRawAudioToTeam(client, team, const String:sSound[255], iVoicePitch = 100, Float:fVoiceMarkShowTime = 1.0){ if(!isClientConnectedIngame(client)){ return false; } for(new i = 1; i <= MaxClients; i++){ if(IsClientInGame(i) && GetClientTeam(i) == team){ new Handle:buffer = StartMessageOne("RawAudio", i); if (buffer != INVALID_HANDLE) { BfWriteByte(buffer, iVoicePitch); BfWriteByte(buffer, client); BfWriteFloat(buffer, fVoiceMarkShowTime); BfWriteString(buffer, sSound); EndMessage(); } } } return true; } stock bool:sendRawAudioToTeamAndSpectator(client, team, const String:sSound[255], iVoicePitch = 100, Float:fVoiceMarkShowTime = 1.0){ if(!isClientConnectedIngame(client)){ return false; } for(new i = 1; i <= MaxClients; i++){ if(IsClientInGame(i)){ new targetTeam = GetClientTeam(i); if(targetTeam == team || targetTeam == TEAM_SPECTATOR){ new Handle:buffer = StartMessageOne("RawAudio", i); if (buffer != INVALID_HANDLE) { BfWriteByte(buffer, iVoicePitch); BfWriteByte(buffer, client); BfWriteFloat(buffer, fVoiceMarkShowTime); BfWriteString(buffer, sSound); EndMessage(); } } } } return true; } stock bool:sendRawAudioToAll(client, const String:sSound[255], iVoicePitch = 100, Float:fVoiceMarkShowTime = 1.0){ if(!isClientConnectedIngame(client)){ return false; } new Handle:buffer = StartMessageAll("RawAudio"); if (buffer != INVALID_HANDLE) { BfWriteByte(buffer, iVoicePitch); BfWriteByte(buffer, client); BfWriteFloat(buffer, fVoiceMarkShowTime); BfWriteString(buffer, sSound); EndMessage(); return true; } return false; } //i dunno, what the hell is this magic number mean, i DUNNO! #define RADIOTEXT_MAGIC_NUMBER 3 stock bool:sendRadioTextTo(client, target, const String:sText[255], any:...){ if(!isClientConnectedIngame(client)){ return false; } new Handle:buffer = StartMessageOne("RadioText", target); if (buffer != INVALID_HANDLE) { decl String:sClientName[255]; decl String:sPlaceName[255]; decl String:msg[255]; GetClientName(client, sClientName, 255); GetEntPropString(client, Prop_Data, "m_szLastPlaceName", sPlaceName, 255); SetGlobalTransTarget(target); VFormat(msg, 255, sText, 4); if(StrEqual(sPlaceName, "", false)){ BfWriteByte(buffer, RADIOTEXT_MAGIC_NUMBER); BfWriteByte(buffer, client); BfWriteString(buffer, "#Game_radio"); BfWriteString(buffer, sClientName); BfWriteString(buffer, msg); }else{ BfWriteByte(buffer, RADIOTEXT_MAGIC_NUMBER); BfWriteByte(buffer, client); BfWriteString(buffer, "#Game_radio_location"); BfWriteString(buffer, sClientName); BfWriteString(buffer, sPlaceName); BfWriteString(buffer, msg); } EndMessage(); return true; } return false; } stock bool:sendRadioTextToAll(client, const String:sText[255], any:...){ if(!isClientConnectedIngame(client)){ return false; } for(new i = 1; i <= MaxClients; i++){ if(IsClientInGame(i)){ new Handle:buffer = StartMessageOne("RadioText", i); if (buffer != INVALID_HANDLE){ decl String:sClientName[255]; decl String:sPlaceName[255]; decl String:msg[255]; GetClientName(client, sClientName, 255); GetEntPropString(client, Prop_Data, "m_szLastPlaceName", sPlaceName, 255); SetGlobalTransTarget(i); VFormat(msg, 255, sText, 3); if(StrEqual(sPlaceName, "", false)){ BfWriteByte(buffer, RADIOTEXT_MAGIC_NUMBER); BfWriteByte(buffer, client); BfWriteString(buffer, "#Game_radio"); BfWriteString(buffer, sClientName); BfWriteString(buffer, msg); }else{ BfWriteByte(buffer, RADIOTEXT_MAGIC_NUMBER); BfWriteByte(buffer, client); BfWriteString(buffer, "#Game_radio_location"); BfWriteString(buffer, sClientName); BfWriteString(buffer, sPlaceName); BfWriteString(buffer, msg); } EndMessage(); } } } return true; } stock bool:sendRadioTextToTeam(client, team, const String:sText[], any:...){ if(!isClientConnectedIngame(client)){ return false; } decl String:sClientName[255]; decl String:sPlaceName[255]; decl String:msg[255]; GetClientName(client, sClientName, 255); GetEntPropString(client, Prop_Data, "m_szLastPlaceName", sPlaceName, 255); for(new i = 1; i <= MaxClients; i++){ if(IsClientInGame(i) && GetClientTeam(i) == team){ SetGlobalTransTarget(i); VFormat(msg, 255, sText, 3); new Handle:buffer = StartMessageOne("RadioText", i); if (buffer != INVALID_HANDLE){ if(StrEqual(sPlaceName, "", false)){ BfWriteByte(buffer, RADIOTEXT_MAGIC_NUMBER); BfWriteByte(buffer, client); BfWriteString(buffer, "#Game_radio"); BfWriteString(buffer, sClientName); BfWriteString(buffer, msg); }else{ BfWriteByte(buffer, RADIOTEXT_MAGIC_NUMBER); BfWriteByte(buffer, client); BfWriteString(buffer, "#Game_radio_location"); BfWriteString(buffer, sClientName); BfWriteString(buffer, sPlaceName); BfWriteString(buffer, msg); } EndMessage(); } } } return true; } stock getAliveClientOnTeam(iTeam){ new iCount = 0; for(new i = 1; i <= MaxClients; i++){ if(isClientConnectedIngameAlive(i) && GetClientTeam(i) == iTeam){ iCount++; } } return iCount; } stock stripClientAllWeapon(client, const String:sServerClassName[]){ new Weapon_Offset = FindSendPropOffs(sServerClassName, "m_hMyWeapons"); new Max_Guns = 48; for(new n = 0; n < Max_Guns; n++){ new iWeaponEntity = GetEntDataEnt2(client, Weapon_Offset + n * 4); if(iWeaponEntity > 0){ RemovePlayerItem(client, iWeaponEntity); AcceptEntityInput(iWeaponEntity, "kill"); } } } stock initVector(Float:vec[3]){ vec[0] = 0.0; vec[1] = 0.0; vec[2] = 0.0; } stock copyVector(Float:from[3], Float:to[3]){ to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; } stock bool:isStringBool(const String:text[], &bool:resultbuffer){ return isStringIntRange(text, 0, 1, any:resultbuffer); } stock bool:isStringColor(const String:text[], &resultbuffer){ return isStringIntRange(text, 0, 255, resultbuffer); } stock bool:isStringInt(const String:text[], &resultbuffer){ new intbuffer = StringToInt(text); if(intbuffer != 0 || StrEqual(text, "0", false) || StrEqual(text, "+0", false) || StrEqual(text, "-0", false)){ //일단 숫자다 resultbuffer = intbuffer; return true; } return false; } stock bool:isStringIntRange(const String:text[], min, max, &resultbuffer){ if(isStringInt(text, resultbuffer)){ return (resultbuffer >= min && resultbuffer <= max); } return false; } stock bool:StripQuotesOnce(String:targetstring[], maxlength){ if(targetstring[0] == '"' && targetstring[strlen(targetstring) - 1] == '"'){ ReplaceStringEx(targetstring, maxlength, "\"", ""); targetstring[strlen(targetstring) - 1] = '\0'; return true; } return false; } //this function will change any dublicated value on array to alternateValue. stock removeDublicatedArrayElement(any:array[], arraysize, any:alternateValue){ for(new i = 0; i < arraysize - 1; i++){ if(array[i] != alternateValue){ for(new searchtarget = i + 1; searchtarget < arraysize; searchtarget++){ if(array[i] == array[searchtarget]){ array[searchtarget] = alternateValue; } } } } } //u should call TE send function via yourself. not working stock bool:setupEffectDispatch(const Float:Origin[3], const Float:Start[3], const Float:Angles[3], const Float:Normal[3], flags, const Float:magnitude, const Float:scale, attachmentindex, surfaceprop, const String:EffectName[], iMaterial, iDamageType, iHitbox, iEntIndex, iColor, Float:radius){ static bool:checkedstringtableid = false; static stringtableid = INVALID_STRING_TABLE; if(!checkedstringtableid){ checkedstringtableid = true; stringtableid = FindStringTable("EffectDispatch"); PrintToServer("%d", stringtableid); } if(stringtableid != INVALID_STRING_TABLE){ TE_Start("EffectDispatch"); TE_WriteVector("m_vOrigin[0]", Origin); TE_WriteVector("m_vStart[0]", Start); TE_WriteVector("m_vAngles", Angles); TE_WriteVector("m_vNormal", Normal); TE_WriteNum("m_fFlags", flags); TE_WriteFloat("m_flMagnitude", magnitude); TE_WriteFloat("m_flScale", scale); TE_WriteNum("m_nAttachmentIndex", attachmentindex); TE_WriteNum("m_nSurfaceProp", surfaceprop); AddToStringTable(stringtableid, EffectName) TE_WriteNum("m_iEffectName", FindStringIndex(stringtableid, EffectName)); PrintToServer("%d", FindStringIndex(stringtableid, EffectName)); TE_WriteNum("m_nMaterial", iMaterial); TE_WriteNum("m_nDamageType", iDamageType); TE_WriteNum("m_nHitBox", iHitbox); TE_WriteNum("entindex", iEntIndex); TE_WriteNum("m_nColor", iColor); TE_WriteFloat("m_flRadius", radius); return true; } return false; } //water effect! notworking stock bool:setupWaterSplashEffect(const Float:origin[3], bool:WaterInSlime, Float:scale, const Float:normal[3] = {0.0, 0.0, 1.0}){ return setupEffectDispatch(origin, NULL_VECTOR, NULL_VECTOR, normal, WaterInSlime, 0.0, scale, 0, 0, "watersplash", 0, 0, 0, INVALID_ENT_REFERENCE, -1, 0.0); }