10 // setup function pointers to AI routines
11 for(int i
=0;i
<OBJ_LAST
;i
++)
12 memset(&objprop
[i
].ai_routines
, 0, sizeof(objprop
[i
].ai_routines
));
14 if (load_npc_tbl()) return 1;
16 // OBJ_NULL has flags set in npc.tbl, but shouldn't be set in our engine
17 objprop
[OBJ_NULL
].defaultflags
= 0;
18 memcpy(&objprop
[OBJ_SKULLHEAD_CARRIED
], &objprop
[OBJ_SKULLHEAD
], sizeof(ObjProp
));
20 objprop
[OBJ_POLISH
].initial_hp
= 24; // is the value of 120 in npc.tbl really wrong? if so why?
21 objprop
[OBJ_POLISH
].death_sound
= 25; // not sure why this is apparently wrong in file
23 // call all the INITFUNC() routines you find at the beginning
24 // of every AI-related module which assign AI logic to objects.
25 if (AIRoutines
.CallFunctions())
27 staterr("ai_init: failed to initilize AIRoutines function pointers");
35 bool load_npc_tbl(void)
37 const int smoke_amounts
[] = { 0, 3, 7, 12 };
38 const int nEntries
= 361;
41 FILE *fp
= fileopen("data/npc.tbl", "rb");
42 if (!fp
) { staterr("load_npc_tbl: data/npc.tbl is missing"); return 1; }
44 stat("Reading npc.tbl...");
46 for(i
=0;i
<nEntries
;i
++) objprop
[i
].defaultflags
= fgeti(fp
);
47 for(i
=0;i
<nEntries
;i
++) objprop
[i
].initial_hp
= fgeti(fp
);
49 // next is a spritesheet # of something--but we don't use it, so skip
50 //for(i=0;i<nEntries;i++) fgetc(fp); // spritesheet # or something--but we don't use it
51 fseek(fp
, (nEntries
* 2 * 2) + nEntries
, SEEK_SET
);
53 for(i
=0;i
<nEntries
;i
++) objprop
[i
].death_sound
= fgetc(fp
);
54 for(i
=0;i
<nEntries
;i
++) objprop
[i
].hurt_sound
= fgetc(fp
);
55 for(i
=0;i
<nEntries
;i
++) objprop
[i
].death_smoke_amt
= smoke_amounts
[fgetc(fp
)];
56 for(i
=0;i
<nEntries
;i
++) objprop
[i
].xponkill
= fgetl(fp
);
57 for(i
=0;i
<nEntries
;i
++) objprop
[i
].damage
= fgetl(fp
);
59 /*for(i=0;i<nEntries;i++)
63 int right = fgetc(fp);
64 int bottom = fgetc(fp);
68 stat("%d %d %d %d", left, top, right, bottom);
69 stat("sprite %d", objprop[i].sprite);
78 void c------------------------------() {}
81 // spawn an object at an enemies action point
82 Object
*SpawnObjectAtActionPoint(Object
*o
, int otype
)
87 x
= o
->x
+ (sprites
[o
->sprite
].frame
[o
->frame
].dir
[o
->dir
].actionpoint
.x
<< CSF
);
88 y
= o
->y
+ (sprites
[o
->sprite
].frame
[o
->frame
].dir
[o
->dir
].actionpoint
.y
<< CSF
);
89 newObject
= CreateObject(x
, y
, otype
);
90 newObject
->dir
= o
->dir
;
95 // destroys all objects of type "otype".
96 // creates a BoomFlash and smoke, but no bonuses.
97 void KillObjectsOfType(int type
)
99 Object
*o
= firstobject
;
104 SmokeClouds(o
, 1, 0, 0);
105 effect(o
->CenterX(), o
->CenterY(), EFFECT_BOOMFLASH
);
114 // deletes all objects of type "otype" silently, without any smoke or other effects.
115 void DeleteObjectsOfType(int type
)
117 Object
*o
= firstobject
;
130 void c------------------------------() {}
134 // handles object blinking: at random intervals forces object o's frame to blinkframe
135 // for blinktime frames.
136 void randblink(Object
*o
, int blinkframe
, int blinktime
, int prob
)
141 o
->frame
= blinkframe
;
143 else if (random(0, prob
) == 0)
145 o
->frame
= blinkframe
;
150 // call this in an object's aftermove routine if it's an object
151 // which is being carried by the player like a puppy or curly.
152 // x_left: offset from p's action point when he faces left
153 // x_right: when he faces right
154 // off_y: vertical offset from p's action point
155 void StickToPlayer(Object
*o
, int x_left
, int x_right
, int off_y
)
159 // needed for puppy in chest
160 o
->flags
&= ~FLAG_SCRIPTONACTIVATE
;
162 // by offsetting from the player's action point, where he holds his gun, we
163 // already have set up for us a nice up-and-down 1 pixel as he walks
164 frame
= player
->frame
;
165 // the p's "up" frames have unusually placed action points so we have to cancel those out
166 if (frame
>= 3 && frame
<= 5) frame
-= 3;
168 x
= (player
->x
>> CSF
) + sprites
[player
->sprite
].frame
[frame
].dir
[player
->dir
].actionpoint
.x
;
169 y
= (player
->y
>> CSF
) + sprites
[player
->sprite
].frame
[frame
].dir
[player
->dir
].actionpoint
.y
;
172 if (player
->dir
== RIGHT
)
188 // used for some bosses with subobjects
189 void transfer_damage(Object
*o
, Object
*target
)
193 // if you forget to set hp to 1000 when creating the puppet object,
194 // it can immediately destroy the main object, possibly leading to crashes.
199 target
->DealDamage(1000 - o
->hp
);
205 void c------------------------------() {}
208 // do the "teleport in" effect for object o.
209 // when complete, returns true.
210 // this function uses o->timer and assume o->timer starts at 0.
211 bool DoTeleportIn(Object
*o
, int slowness
)
213 if (teleffect(o
, slowness
, false))
215 o
->clip_enable
= false;
222 // does a teleport out effect.
223 // When complete, returns true.
224 // this function uses o->timer and assume o->timer starts at 0.
225 bool DoTeleportOut(Object
*o
, int slowness
)
227 return teleffect(o
, slowness
, true);
230 // common code for DoTeleportIn and DoTeleportOut
231 // returns true when teleport is complete
232 static bool teleffect(Object
*o
, int slowness
, bool teleporting_out
)
234 o
->display_xoff
= random(-1, 1);
239 o
->clip_enable
= true;
243 if (++o
->timer
>= (sprites
[o
->sprite
].h
<< slowness
))
245 o
->clip_enable
= false;
251 int amt
= (o
->timer
>> slowness
);
254 o
->clipy2
= sprites
[o
->sprite
].h
- amt
;
263 void c------------------------------() {}
266 void ai_animate1(Object
*o
) { if (++o
->frame
>= sprites
[o
->sprite
].nframes
) o
->frame
= 0; }
267 void ai_animate2(Object
*o
) { simpleanim(o
, 2); }
268 void ai_animate3(Object
*o
) { simpleanim(o
, 3); }
269 void ai_animate4(Object
*o
) { simpleanim(o
, 4); }
270 void ai_animate5(Object
*o
) { simpleanim(o
, 5); }
272 static void simpleanim(Object
*o
, int spd
)
274 if (++o
->animtimer
>= spd
)
277 if (++o
->frame
>= sprites
[o
->sprite
].nframes
) o
->frame
= 0;
282 void c------------------------------() {}
285 // aftermove routine which sticks the object to the action point of the NPC that's carrying it
286 void aftermove_StickToLinkedActionPoint(Object
*o
)
288 Object
*link
= o
->linkedobject
;
293 dir
= (link
->dir
^ o
->carry
.flip
);
295 o
->x
= ((link
->x
>> CSF
) + sprites
[link
->sprite
].frame
[link
->frame
].dir
[dir
].actionpoint
.x
) << CSF
;
296 o
->y
= ((link
->y
>> CSF
) + sprites
[link
->sprite
].frame
[link
->frame
].dir
[dir
].actionpoint
.y
) << CSF
;
305 void onspawn_snap_to_ground(Object
*o
)
310 void onspawn_set_frame_from_id2(Object
*o
)
316 void c------------------------------() {}