Skip to content

Commit 1227501

Browse files
committed
add example for monster_base entity
1 parent 081a5e5 commit 1227501

File tree

1 file changed

+216
-0
lines changed

1 file changed

+216
-0
lines changed
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
Here is an example how to implement HL Zombie using monster_base entity. You can test zombies on map `c1a1a`.
2+
3+
```cpp
4+
#include <amxmodx>
5+
#include <fakemeta>
6+
#include <hamsandwich>
7+
#include <xs>
8+
9+
#include <api_custom_entities>
10+
11+
#include <entity_base_monster_const>
12+
13+
#define ENTITY_NAME "monster_zombie"
14+
15+
#define ZOMBIE_AE_ATTACK_RIGHT 0x01
16+
#define ZOMBIE_AE_ATTACK_LEFT 0x02
17+
#define ZOMBIE_AE_ATTACK_BOTH 0x03
18+
19+
#define ZOMBIE_FLINCH_DELAY 2.0
20+
21+
#define m_flNextFlinch "flNextFlinch"
22+
23+
new const g_szModel[] = "models/zombie.mdl";
24+
25+
new const g_rgpAttackHitSounds[][] = {
26+
"zombie/claw_strike1.wav",
27+
"zombie/claw_strike2.wav",
28+
"zombie/claw_strike3.wav",
29+
};
30+
31+
new const g_rgpAttackMissSounds[][] = {
32+
"zombie/claw_miss1.wav",
33+
"zombie/claw_miss2.wav",
34+
};
35+
36+
new const g_rgpAttackSounds[][] = {
37+
"zombie/zo_attack1.wav",
38+
"zombie/zo_attack2.wav",
39+
};
40+
41+
new const g_rgpIdleSounds[][] = {
42+
"zombie/zo_idle1.wav",
43+
"zombie/zo_idle2.wav",
44+
"zombie/zo_idle3.wav",
45+
"zombie/zo_idle4.wav",
46+
};
47+
48+
new const g_rgpAlertSounds[][] = {
49+
"zombie/zo_alert10.wav",
50+
"zombie/zo_alert20.wav",
51+
"zombie/zo_alert30.wav",
52+
};
53+
54+
new const g_rgpPainSounds[][] = {
55+
"zombie/zo_pain1.wav",
56+
"zombie/zo_pain2.wav",
57+
};
58+
59+
public plugin_precache() {
60+
precache_model(g_szModel);
61+
62+
for (new i = 0; i < sizeof(g_rgpAttackHitSounds); ++i) precache_sound(g_rgpAttackHitSounds[i]);
63+
for (new i = 0; i < sizeof(g_rgpAttackMissSounds); ++i) precache_sound(g_rgpAttackMissSounds[i]);
64+
for (new i = 0; i < sizeof(g_rgpAttackSounds); ++i) precache_sound(g_rgpAttackSounds[i]);
65+
for (new i = 0; i < sizeof(g_rgpIdleSounds); ++i) precache_sound(g_rgpIdleSounds[i]);
66+
for (new i = 0; i < sizeof(g_rgpAlertSounds); ++i) precache_sound(g_rgpAlertSounds[i]);
67+
for (new i = 0; i < sizeof(g_rgpPainSounds); ++i) precache_sound(g_rgpPainSounds[i]);
68+
69+
CE_RegisterDerived(ENTITY_NAME, BASE_MONSTER_ENTITY_NAME);
70+
71+
CE_RegisterHook(ENTITY_NAME, CEFunction_Init, "@Entity_Init");
72+
CE_RegisterHook(ENTITY_NAME, CEFunction_InitPhysics, "@Entity_InitPhysics");
73+
CE_RegisterHook(ENTITY_NAME, CEFunction_Spawned, "@Entity_Spawned");
74+
75+
CE_RegisterVirtualMethod(ENTITY_NAME, IgnoreConditions, "@Entity_IgnoreConditions");
76+
CE_RegisterVirtualMethod(ENTITY_NAME, SetYawSpeed, "@Entity_SetYawSpeed");
77+
CE_RegisterVirtualMethod(ENTITY_NAME, HandleAnimEvent, "@Entity_HandleAnimEvent", CE_MP_Cell, CE_MP_Array, 64);
78+
79+
CE_RegisterMethod(ENTITY_NAME, AlertSound, "@Entity_AlertSound");
80+
CE_RegisterMethod(ENTITY_NAME, IdleSound, "@Entity_IdleSound");
81+
CE_RegisterMethod(ENTITY_NAME, PainSound, "@Entity_PainSound");
82+
83+
CE_RegisterVirtualMethod(ENTITY_NAME, Classify, "@Entity_Classify");
84+
}
85+
86+
public plugin_init() {
87+
register_plugin("[Entity] Zombie Monster", "1.0.0", "Hedgehog Fog");
88+
}
89+
90+
@Entity_Init(this) {
91+
CE_SetMemberVec(this, CE_MEMBER_MINS, Float:{-16.0, -16.0, 0.0});
92+
CE_SetMemberVec(this, CE_MEMBER_MAXS, Float:{16.0, 16.0, 72.0});
93+
CE_SetMemberString(this, CE_MEMBER_MODEL, g_szModel, false);
94+
CE_SetMember(this, CE_MEMBER_BLOODCOLOR, 195);
95+
}
96+
97+
@Entity_InitPhysics(this) {
98+
set_pev(this, pev_solid, SOLID_SLIDEBOX);
99+
set_pev(this, pev_movetype, MOVETYPE_STEP);
100+
}
101+
102+
@Entity_Spawned(this) {
103+
set_pev(this, pev_spawnflags, pev(this, pev_spawnflags) | SF_MONSTER_FADECORPSE);
104+
set_pev(this, pev_health, 100.0);
105+
set_pev(this, pev_view_ofs, Float:{0.0, 0.0, 28.0});
106+
CE_SetMember(this, m_flFieldOfView, 0.5);
107+
CE_SetMember(this, m_iMonsterState, MONSTER_STATE_NONE);
108+
109+
CE_SetMember(this, m_flMeleeAttack1Range, 70.0);
110+
CE_SetMember(this, m_flMeleeAttack1Damage, 10.0);
111+
112+
CE_SetMember(this, m_flMeleeAttack2Range, 70.0);
113+
CE_SetMember(this, m_flMeleeAttack2Damage, 24.0);
114+
}
115+
116+
@Entity_AlertSound(this) {
117+
emit_sound(this, CHAN_WEAPON, g_rgpAlertSounds[random(sizeof(g_rgpAlertSounds))], VOL_NORM, ATTN_NORM, 0, 100 + random_num(-5, 5));
118+
}
119+
120+
@Entity_IdleSound(this) {
121+
emit_sound(this, CHAN_WEAPON, g_rgpIdleSounds[random(sizeof(g_rgpIdleSounds))], VOL_NORM, ATTN_NORM, 0, 100 + random_num(-5, 5));
122+
}
123+
124+
@Entity_PainSound(this) {
125+
emit_sound(this, CHAN_WEAPON, g_rgpPainSounds[random(sizeof(g_rgpPainSounds))], VOL_NORM, ATTN_NORM, 0, 100 + random_num(-5, 5));
126+
}
127+
128+
@Entity_SetYawSpeed(this) {
129+
set_pev(this, pev_yaw_speed, 120.0);
130+
}
131+
132+
@Entity_HandleAnimEvent(this, iEventId, const rgOptions[]) {
133+
CE_CallBaseMethod(iEventId, rgOptions);
134+
135+
static Float:vecAimAngles[3];
136+
pev(this, pev_angles, vecAimAngles);
137+
vecAimAngles[0] = -vecAimAngles[0];
138+
139+
static Float:vecForward[3]; angle_vector(vecAimAngles, ANGLEVECTOR_FORWARD, vecForward);
140+
static Float:vecRight[3]; angle_vector(vecAimAngles, ANGLEVECTOR_RIGHT, vecRight);
141+
142+
switch (iEventId) {
143+
case ZOMBIE_AE_ATTACK_RIGHT, ZOMBIE_AE_ATTACK_LEFT, ZOMBIE_AE_ATTACK_BOTH: {
144+
static pHurt; pHurt = CE_CallMethod(this, ZOMBIE_AE_ATTACK_BOTH ? MeleeAttack2 : MeleeAttack1);
145+
146+
if (pHurt != FM_NULLENT && pev(pHurt, pev_flags) & (FL_MONSTER | FL_CLIENT)) {
147+
static Float:vecVictimPunchAngle[3]; pev(pHurt, pev_punchangle, vecVictimPunchAngle);
148+
static Float:vecVictimVelocity[3]; pev(pHurt, pev_velocity, vecVictimVelocity);
149+
150+
vecVictimPunchAngle[0] = 5.0;
151+
152+
switch (iEventId) {
153+
case ZOMBIE_AE_ATTACK_RIGHT, ZOMBIE_AE_ATTACK_LEFT: {
154+
static iDirection; iDirection = (iEventId == ZOMBIE_AE_ATTACK_RIGHT ? -1 : 1);
155+
156+
vecVictimPunchAngle[2] = (18.0 * iDirection);
157+
xs_vec_add_scaled(vecVictimVelocity, vecRight, 100.0 * iDirection, vecVictimVelocity);
158+
}
159+
case ZOMBIE_AE_ATTACK_BOTH: {
160+
xs_vec_add_scaled(vecVictimVelocity, vecForward, 100.0, vecVictimVelocity);
161+
}
162+
}
163+
164+
set_pev(pHurt, pev_punchangle, vecVictimPunchAngle);
165+
set_pev(pHurt, pev_velocity, vecVictimVelocity);
166+
}
167+
168+
if (pHurt != FM_NULLENT) {
169+
emit_sound(this, CHAN_WEAPON, g_rgpAttackHitSounds[random(sizeof(g_rgpAttackHitSounds))], VOL_NORM, ATTN_NORM, 0, 100 + random_num(-5, 5));
170+
} else {
171+
emit_sound(this, CHAN_WEAPON, g_rgpAttackMissSounds[random(sizeof(g_rgpAttackMissSounds))], VOL_NORM, ATTN_NORM, 0, 100 + random_num(-5, 5));
172+
}
173+
174+
if (random(2)) @Entity_AttackSound(this);
175+
}
176+
case SCRIPT_EVENT_SOUND: {
177+
if (equal(rgOptions, "common/npc_step", 15)) {
178+
CE_CallMethod(this, StepSound);
179+
}
180+
}
181+
default: {
182+
// CE_CallBaseMethod(iEventId, rgOptions);
183+
}
184+
}
185+
}
186+
187+
@Entity_AttackSound(this) {
188+
emit_sound(this, CHAN_VOICE, g_rgpAttackSounds[random(sizeof(g_rgpAttackSounds))], VOL_NORM, ATTN_NORM, 0, 100 + random_num(-5, 5));
189+
}
190+
191+
@Entity_Classify(this) {
192+
return CLASS_ALIEN_MONSTER;
193+
}
194+
195+
@Entity_IgnoreConditions(this) {
196+
new iIgnore = CE_CallBaseMethod();
197+
198+
static Float:flGameTime; flGameTime = get_gametime();
199+
static Float:flNextFlinch; flNextFlinch = CE_GetMember(this, m_flNextFlinch);
200+
static Activity:iActivity; iActivity = CE_GetMember(this, m_iActivity);
201+
202+
if ((iActivity == ACT_MELEE_ATTACK1) || (iActivity == ACT_MELEE_ATTACK1)) {
203+
if (flNextFlinch >= flGameTime) {
204+
iIgnore |= (COND_LIGHT_DAMAGE | COND_HEAVY_DAMAGE);
205+
}
206+
}
207+
208+
if ((iActivity == ACT_SMALL_FLINCH) || (iActivity == ACT_BIG_FLINCH)) {
209+
if (flNextFlinch < flGameTime) {
210+
flNextFlinch = flGameTime + ZOMBIE_FLINCH_DELAY;
211+
}
212+
}
213+
214+
return iIgnore;
215+
}
216+
```

0 commit comments

Comments
 (0)