Crossfire Server, Branches 1.12  R18729
citylife.c
Go to the documentation of this file.
1 /*****************************************************************************/
2 /* Template for version 2.0 plugins. */
3 /* Contact: yann.chachkoff@myrealbox.com */
4 /*****************************************************************************/
5 /* That code is placed under the GNU General Public Licence (GPL) */
6 /* (C)2001-2005 by Chachkoff Yann (Feel free to deliver your complaints) */
7 /*****************************************************************************/
8 /* CrossFire, A Multiplayer game for X-windows */
9 /* */
10 /* Copyright (C) 2000 Mark Wedel */
11 /* Copyright (C) 1992 Frank Tore Johansen */
12 /* */
13 /* This program is free software; you can redistribute it and/or modify */
14 /* it under the terms of the GNU General Public License as published by */
15 /* the Free Software Foundation; either version 2 of the License, or */
16 /* (at your option) any later version. */
17 /* */
18 /* This program is distributed in the hope that it will be useful, */
19 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
20 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
21 /* GNU General Public License for more details. */
22 /* */
23 /* You should have received a copy of the GNU General Public License */
24 /* along with this program; if not, write to the Free Software */
25 /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
26 /* */
27 /*****************************************************************************/
28 
61 #include <citylife.h>
62 #include <stdarg.h>
63 #ifndef __CEXTRACT__
64 #include <citylife_proto.h>
65 #endif
66 
67 CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr) {
68  cf_init_plugin(gethooksptr);
69 
70  cf_log(llevDebug, PLUGIN_VERSION " init\n");
71 
72  return 0;
73 }
74 
75 CF_PLUGIN void *getPluginProperty(int *type, ...) {
76  va_list args;
77  const char *propname;
78  int size;
79  char *buf;
80 
81  va_start(args, type);
82  propname = va_arg(args, const char *);
83 
84  if (!strcmp(propname, "Identification")) {
85  buf = va_arg(args, char *);
86  size = va_arg(args, int);
87  va_end(args);
88  snprintf(buf, size, PLUGIN_NAME);
89  return NULL;
90  } else if (!strcmp(propname, "FullName")) {
91  buf = va_arg(args, char *);
92  size = va_arg(args, int);
93  va_end(args);
94  snprintf(buf, size, PLUGIN_VERSION);
95  return NULL;
96  }
97  va_end(args);
98  return NULL;
99 }
100 
101 CF_PLUGIN int citylife_runPluginCommand(object *op, char *params) {
102  return -1;
103 }
104 
106 #define FIRST_MOVE_KEY "citylife_first_move"
107 
111 typedef struct {
112  int x;
113  int y;
114 } spawn_point;
115 
120 typedef struct {
121  int sx, sy, ex, ey;
122 } spawn_zone;
123 
127 typedef struct {
130  const spawn_zone *zones;
133  const char *mapname;
134  const char *const *available_archetypes;
136 } mapzone;
147 static const spawn_zone scorn_nw_zones[] = {
148  { 40, 26, 50, 50 }
149 };
150 
152 static const spawn_point scorn_nw_points[] = {
153  { 41, 37 },
154  { 48, 35 },
155  { 49, 40 },
156  { 47, 22 },
157  { 49, 37 }
158 };
159 
161 static const spawn_zone scorn_ne_zones[] = {
162  { 0, 26, 22, 50 }
163 };
164 
166 static const spawn_point scorn_ne_points[] = {
167  { 15, 42 },
168  { 9, 35 },
169  { 15, 29 },
170  { 1, 25 },
171  { 1, 29 }
172 };
173 
175 static const spawn_zone scorn_sw_zones[] = {
176  { 41, 0, 50, 10 }
177 };
178 
180 static const spawn_point scorn_sw_points[] = {
181  { 41, 2 },
182  { 46, 8 },
183  { 42, 8 }
184 };
185 
187 static const spawn_zone scorn_se_zones[] = {
188  { 0, 0, 13, 10 }
189 };
190 
192 static const spawn_point scorn_se_points[] = {
193  { 2, 8 },
194  { 11, 8 },
195  { 8, 1 },
196  { 5, 8 }
197 };
198 
200 static const char *const scorn_archs[] = {
201  "c_man",
202  "c_woman",
203  "child",
204  "farmer",
205  "fatman",
206  "fatwoman",
207  "guard",
208  "knight",
209  "man",
210  "nun",
211  "sage",
212  "woman"
213 };
221 static const mapzone available_zones[] = {
222  { scorn_nw_points, 5, scorn_nw_zones, 1, 2, "/world/world_104_115", scorn_archs, 12 },
223  { scorn_ne_points, 1, scorn_ne_zones, 1, 5, "/world/world_105_115", scorn_archs, 12 },
224  { scorn_sw_points, 3, scorn_sw_zones, 1, 5, "/world/world_104_116", scorn_archs, 12 },
225  { scorn_se_points, 1, scorn_se_zones, 1, 5, "/world/world_105_116", scorn_archs, 12 },
226  { NULL, -1, NULL, -1, 1, "", NULL, 0 },
227 };
228 
237 static const mapzone *get_zone_for_map(mapstruct *map) {
238  int test;
239 
240  for (test = 0; available_zones[test].count_points != -1; test++) {
241  if (strcmp(available_zones[test].mapname, map->path) == 0)
242  return &available_zones[test];
243  }
244  return NULL;
245 }
246 
254 static object *get_npc(const mapzone *zone) {
255  int arch = RANDOM()%zone->archetypes_count;
256  object *npc = cf_create_object_by_name(zone->available_archetypes[arch]);
257  object *evt;
258 
259  if (!npc) {
260  cf_log(llevError, PLUGIN_NAME ": get_npc() got NULL object for %s!\n", zone->available_archetypes[arch]);
261  return NULL;
262  }
263 
265  /* Prevent disease spreading in Scorn, mostly rabies. */
267  /* add a key so NPC will not disappear in the house it came from */
268  cf_object_set_key(npc, FIRST_MOVE_KEY, "1", 1);
269 
270  evt = cf_create_object_by_name("event_time");
273  cf_object_insert_object(evt, npc);
274 
275  return npc;
276 }
277 
285 static void add_npc_to_zone(const mapzone *zone, mapstruct *map) {
286  int which;
287  object *npc = get_npc(zone);
288 
289  if (!npc)
290  return;
291  which = RANDOM()%zone->count_zones;
292  if (cf_object_teleport(npc, map, zone->zones[which].sx+RANDOM()%(zone->zones[which].ex-zone->zones[which].sx), zone->zones[which].sy+RANDOM()%(zone->zones[which].ey-zone->zones[which].sy))) {
293  cf_object_free(npc);
294  }
295 }
296 
304 static void add_npc_to_point(const mapzone *zone, mapstruct *map) {
305  int which;
306  object *npc = get_npc(zone);
307 
308  which = RANDOM()%zone->count_points;
309  if (cf_object_teleport(npc, map, zone->points[which].x, zone->points[which].y)) {
310  cf_object_free(npc);
311  }
312 }
313 
319 static void add_npcs_to_map(mapstruct *map) {
320  int add;
321  const mapzone *zone = get_zone_for_map(map);
322 
323  if (!zone)
324  return;
325 
326  add = 1+RANDOM()%zone->population;
327  cf_log(llevDebug, PLUGIN_NAME ": adding %d NPC to map %s.\n", add, map->path);
328 
329  while (add-- >= 0) {
330  add_npc_to_zone(zone, map);
331  }
332 }
333 
337 static void add_npc_to_random_map(void) {
338  int count, test;
339  mapstruct *list[50];
340  int zones[50];
341  count = 0;
342 
343  cf_log(llevDebug, PLUGIN_NAME ": adding NPC to random map.\n");
344 
345  for (test = 0; available_zones[test].count_points != -1 && count < 50; test++) {
346  if ((list[count] = cf_map_has_been_loaded(available_zones[test].mapname)) && (list[count]->in_memory == MAP_IN_MEMORY)) {
347  zones[count] = test;
348  count++;
349  }
350  }
351  if (!count)
352  return;
353 
354  test = RANDOM()%count;
355  add_npc_to_point(&available_zones[zones[test]], list[test]);
356 }
357 
359  va_list args;
360  static int rv = 0;
361  mapstruct *map;
362  int code;
363 
364  va_start(args, type);
365  code = va_arg(args, int);
366 
367  rv = 0;
368 
369  switch (code) {
370  case EVENT_MAPLOAD:
371  map = va_arg(args, mapstruct *);
372  add_npcs_to_map(map);
373  break;
374 
375  case EVENT_CLOCK:
376  if (RANDOM()%40 == 0)
378  }
379  va_end(args);
380 
381  return &rv;
382 }
383 
385  cf_log(llevDebug, PLUGIN_VERSION " post init\n");
386 
387  /* Pick the global events you want to monitor from this plugin */
388 
389 /*
390  cf_system_register_global_event(EVENT_BORN, PLUGIN_NAME, citylife_globalEventListener);
391  cf_system_register_global_event(EVENT_CRASH, PLUGIN_NAME, citylife_globalEventListener);
392  cf_system_register_global_event(EVENT_PLAYER_DEATH, PLUGIN_NAME, citylife_globalEventListener);
393  cf_system_register_global_event(EVENT_GKILL, PLUGIN_NAME, citylife_globalEventListener);
394  cf_system_register_global_event(EVENT_LOGIN, PLUGIN_NAME, citylife_globalEventListener);
395  cf_system_register_global_event(EVENT_LOGOUT, PLUGIN_NAME, citylife_globalEventListener);
396  cf_system_register_global_event(EVENT_MAPENTER, PLUGIN_NAME, citylife_globalEventListener);
397  cf_system_register_global_event(EVENT_MAPLEAVE, PLUGIN_NAME, citylife_globalEventListener);
398  cf_system_register_global_event(EVENT_MAPRESET, PLUGIN_NAME, citylife_globalEventListener);
399  cf_system_register_global_event(EVENT_REMOVE, PLUGIN_NAME, citylife_globalEventListener);
400  cf_system_register_global_event(EVENT_SHOUT, PLUGIN_NAME, citylife_globalEventListener);
401  cf_system_register_global_event(EVENT_TELL, PLUGIN_NAME, citylife_globalEventListener);
402  cf_system_register_global_event(EVENT_MUZZLE, PLUGIN_NAME, citylife_globalEventListener);
403  cf_system_register_global_event(EVENT_KICK, PLUGIN_NAME, citylife_globalEventListener);
404 */
407 /*
408  cf_system_register_global_event(EVENT_MAPRESET, PLUGIN_NAME, citylife_globalEventListener);
409 */
410 
411  return 0;
412 }
413 
414 CF_PLUGIN void *eventListener(int *type, ...) {
415  static int rv = 1;
416  va_list args;
417  char *buf;
418  object *ground, *who, *activator, *third, *event;
419  int fix;
420  const char *value;
421 
422  va_start(args, type);
423 
424  who = va_arg(args, object *);
425  activator = va_arg(args, object *);
426  third = va_arg(args, object *);
427  buf = va_arg(args, char *);
428  fix = va_arg(args, int);
429  event = va_arg(args, object *);
430  va_end(args);
431 
432  /* should our npc disappear? */
433  if (RANDOM()%100 < 30) {
434  for (ground = cf_map_get_object_at(who->map, who->x, who->y); ground; ground = cf_object_get_object_property(ground, CFAPI_OBJECT_PROP_OB_ABOVE)) {
435  if (ground->type == EXIT) {
436  object *inv;
437 
438  value = cf_object_get_key(who, FIRST_MOVE_KEY);
439  if (strcmp(value, "1") == 0) {
440  cf_object_set_key(who, FIRST_MOVE_KEY, "0", 1);
441  break;
442  }
443 
444  /* must set inventory as no drop, else it'll just drop on the ground */
447 
448  cf_log(llevDebug, PLUGIN_NAME ": NPC entering building.\n");
449  cf_object_remove(who);
450  cf_object_free(who);
451  return &rv;
452  }
453  }
454  }
455 
456  /* we have to move manually, because during the night NPCs don't move. */
457  cf_object_move(who, 1+RANDOM()%8, NULL);
458 
459  return &rv;
460 }
461 
463  cf_log(llevDebug, PLUGIN_VERSION " closing\n");
464  return 0;
465 }
static const spawn_point scorn_se_points[]
Definition: citylife.c:192
static const spawn_zone scorn_nw_zones[]
Definition: citylife.c:147
char path[HUGE_BUF]
Definition: map.h:384
#define FLAG_NO_DROP
Definition: define.h:585
#define CFAPI_OBJECT_PROP_OB_BELOW
Definition: plugin.h:167
const char * cf_object_get_key(object *op, const char *keyname)
static const spawn_point scorn_nw_points[]
Definition: citylife.c:152
void cf_object_set_flag(object *ob, int flag, int value)
static const spawn_point scorn_ne_points[]
Definition: citylife.c:166
#define CFAPI_OBJECT_PROP_INVENTORY
Definition: plugin.h:170
int count_points
Definition: citylife.c:129
static const house_zone_struct zones[]
Definition: cfrhg.c:65
const char * slaying
Definition: object.h:172
void *(* f_plug_api)(int *type,...)
Definition: plugin.h:121
#define FIRST_MOVE_KEY
Definition: citylife.c:106
sint16 x
Definition: object.h:179
void cf_system_register_global_event(int event, const char *name, f_plug_api hook)
sstring cf_add_string(const char *str)
const spawn_zone * zones
Definition: citylife.c:130
CF_PLUGIN int postInitPlugin(void)
Definition: citylife.c:384
CF_PLUGIN int closePlugin(void)
Definition: citylife.c:462
static object * get_npc(const mapzone *zone)
Definition: citylife.c:254
static const spawn_point scorn_sw_points[]
Definition: citylife.c:180
static void add_npc_to_random_map(void)
Definition: citylife.c:337
void cf_log(LogLevel logLevel, const char *format,...)
CF_PLUGIN void * getPluginProperty(int *type,...)
Definition: citylife.c:75
CF_PLUGIN void * citylife_globalEventListener(int *type,...)
Definition: citylife.c:358
#define FLAG_UNDEAD
Definition: define.h:566
#define MAP_IN_MEMORY
Definition: map.h:151
const char * title
Definition: object.h:170
int cf_init_plugin(f_plug_api getHooks)
CF_PLUGIN void * eventListener(int *type,...)
Definition: citylife.c:414
struct mapdef * map
Definition: object.h:155
static void add_npc_to_zone(const mapzone *zone, mapstruct *map)
Definition: citylife.c:285
#define PLUGIN_NAME
Definition: cfanim.h:32
static const mapzone available_zones[]
Definition: citylife.c:221
object * cf_object_insert_object(object *op, object *container)
sint16 y
Definition: object.h:179
const spawn_point * points
Definition: citylife.c:128
static void add_npc_to_point(const mapzone *zone, mapstruct *map)
Definition: citylife.c:304
#define EVENT_MAPLOAD
Definition: plugin.h:95
#define EXIT
Definition: define.h:228
static const spawn_zone scorn_ne_zones[]
Definition: citylife.c:161
void cf_object_remove(object *op)
object * cf_map_get_object_at(mapstruct *m, int x, int y)
CF_PLUGIN int citylife_runPluginCommand(object *op, char *params)
Definition: citylife.c:101
static const spawn_zone scorn_se_zones[]
Definition: citylife.c:187
object * cf_object_get_object_property(object *op, int propcode)
#define EVENT_CLOCK
Definition: plugin.h:80
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
#define CF_PLUGIN
Definition: plugin_common.h:35
int cf_object_move(object *op, int dir, object *originator)
static const spawn_zone scorn_sw_zones[]
Definition: citylife.c:175
mapstruct * cf_map_has_been_loaded(const char *name)
int count_zones
Definition: citylife.c:131
static const char *const scorn_archs[]
Definition: citylife.c:200
static const mapzone * get_zone_for_map(mapstruct *map)
Definition: citylife.c:237
int cf_object_teleport(object *ob, mapstruct *map, int x, int y)
#define FLAG_RANDOM_MOVE
Definition: define.h:606
static void add_npcs_to_map(mapstruct *map)
Definition: citylife.c:319
Definition: map.h:346
void cf_object_free(object *ob)
const char * mapname
Definition: citylife.c:133
#define CFAPI_OBJECT_PROP_OB_ABOVE
Definition: plugin.h:166
object * cf_create_object_by_name(const char *name)
int archetypes_count
Definition: citylife.c:135
const char *const * available_archetypes
Definition: citylife.c:134
int population
Definition: citylife.c:132
uint8 type
Definition: object.h:189
CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr)
Definition: citylife.c:67
int cf_object_set_key(object *op, const char *keyname, const char *value, int add_key)
#define PLUGIN_VERSION
Definition: cfanim.h:33