00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00061 #include <citylife.h>
00062 #include <stdarg.h>
00063 #ifndef __CEXTRACT__
00064 #include <citylife_proto.h>
00065 #endif
00066
00067 CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr) {
00068 cf_init_plugin(gethooksptr);
00069
00070 cf_log(llevDebug, PLUGIN_VERSION " init\n");
00071
00072 return 0;
00073 }
00074
00075 CF_PLUGIN void *getPluginProperty(int *type, ...) {
00076 va_list args;
00077 const char *propname;
00078 int size;
00079 char *buf;
00080
00081 va_start(args, type);
00082 propname = va_arg(args, const char *);
00083
00084 if (!strcmp(propname, "Identification")) {
00085 buf = va_arg(args, char *);
00086 size = va_arg(args, int);
00087 va_end(args);
00088 snprintf(buf, size, PLUGIN_NAME);
00089 return NULL;
00090 } else if (!strcmp(propname, "FullName")) {
00091 buf = va_arg(args, char *);
00092 size = va_arg(args, int);
00093 va_end(args);
00094 snprintf(buf, size, PLUGIN_VERSION);
00095 return NULL;
00096 }
00097 va_end(args);
00098 return NULL;
00099 }
00100
00101 CF_PLUGIN int citylife_runPluginCommand(object *op, char *params) {
00102 return -1;
00103 }
00104
00106 #define FIRST_MOVE_KEY "citylife_first_move"
00107
00111 typedef struct {
00112 int x;
00113 int y;
00114 } spawn_point;
00115
00120 typedef struct {
00121 int sx, sy, ex, ey;
00122 } spawn_zone;
00123
00127 typedef struct {
00128 const spawn_point *points;
00129 int count_points;
00130 const spawn_zone *zones;
00131 int count_zones;
00132 int population;
00133 const char *mapname;
00134 const char *const *available_archetypes;
00135 int archetypes_count;
00136 } mapzone;
00147 static const spawn_zone scorn_nw_zones[] = {
00148 { 40, 26, 50, 50 }
00149 };
00150
00152 static const spawn_point scorn_nw_points[] = {
00153 { 41, 37 },
00154 { 48, 35 },
00155 { 49, 40 },
00156 { 47, 22 },
00157 { 49, 37 }
00158 };
00159
00161 static const spawn_zone scorn_ne_zones[] = {
00162 { 0, 26, 22, 50 }
00163 };
00164
00166 static const spawn_point scorn_ne_points[] = {
00167 { 15, 42 },
00168 { 9, 35 },
00169 { 15, 29 },
00170 { 1, 25 },
00171 { 1, 29 }
00172 };
00173
00175 static const spawn_zone scorn_sw_zones[] = {
00176 { 41, 0, 50, 10 }
00177 };
00178
00180 static const spawn_point scorn_sw_points[] = {
00181 { 41, 2 },
00182 { 46, 8 },
00183 { 42, 8 }
00184 };
00185
00187 static const spawn_zone scorn_se_zones[] = {
00188 { 0, 0, 13, 10 }
00189 };
00190
00192 static const spawn_point scorn_se_points[] = {
00193 { 2, 8 },
00194 { 11, 8 },
00195 { 8, 1 },
00196 { 5, 8 }
00197 };
00198
00200 static const char *const scorn_archs[] = {
00201 "c_man",
00202 "c_woman",
00203 "child",
00204 "farmer",
00205 "fatman",
00206 "fatwoman",
00207 "guard",
00208 "knight",
00209 "man",
00210 "nun",
00211 "sage",
00212 "woman"
00213 };
00221 static const mapzone available_zones[] = {
00222 { scorn_nw_points, 5, scorn_nw_zones, 1, 2, "/world/world_104_115", scorn_archs, 12 },
00223 { scorn_ne_points, 1, scorn_ne_zones, 1, 5, "/world/world_105_115", scorn_archs, 12 },
00224 { scorn_sw_points, 3, scorn_sw_zones, 1, 5, "/world/world_104_116", scorn_archs, 12 },
00225 { scorn_se_points, 1, scorn_se_zones, 1, 5, "/world/world_105_116", scorn_archs, 12 },
00226 { NULL, -1, NULL, -1, 1, "", NULL, 0 },
00227 };
00228
00237 static const mapzone *get_zone_for_map(mapstruct *map) {
00238 int test;
00239
00240 for (test = 0; available_zones[test].count_points != -1; test++) {
00241 if (strcmp(available_zones[test].mapname, map->path) == 0)
00242 return &available_zones[test];
00243 }
00244 return NULL;
00245 }
00246
00254 static object *get_npc(const mapzone *zone) {
00255 int arch = RANDOM()%zone->archetypes_count;
00256 object *npc = cf_create_object_by_name(zone->available_archetypes[arch]);
00257 object *evt;
00258
00259 if (!npc) {
00260 cf_log(llevError, PLUGIN_NAME ": get_npc() got NULL object for %s!\n", zone->available_archetypes[arch]);
00261 return NULL;
00262 }
00263
00264 cf_object_set_flag(npc, FLAG_RANDOM_MOVE, 1);
00265
00266 cf_object_set_flag(npc, FLAG_UNDEAD, 1);
00267
00268 cf_object_set_key(npc, FIRST_MOVE_KEY, "1", 1);
00269
00270 evt = cf_create_object_by_name("event_time");
00271 evt->slaying = cf_add_string(PLUGIN_NAME);
00272 evt->title = cf_add_string(PLUGIN_NAME);
00273 cf_object_insert_object(evt, npc);
00274
00275 return npc;
00276 }
00277
00285 static void add_npc_to_zone(const mapzone *zone, mapstruct *map) {
00286 int which;
00287 object *npc = get_npc(zone);
00288
00289 if (!npc)
00290 return;
00291 which = RANDOM()%zone->count_zones;
00292 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))) {
00293 cf_object_free(npc);
00294 }
00295 }
00296
00304 static void add_npc_to_point(const mapzone *zone, mapstruct *map) {
00305 int which;
00306 object *npc = get_npc(zone);
00307
00308 which = RANDOM()%zone->count_points;
00309 if (cf_object_teleport(npc, map, zone->points[which].x, zone->points[which].y)) {
00310 cf_object_free(npc);
00311 }
00312 }
00313
00319 static void add_npcs_to_map(mapstruct *map) {
00320 int add;
00321 const mapzone *zone = get_zone_for_map(map);
00322
00323 if (!zone)
00324 return;
00325
00326 add = 1+RANDOM()%zone->population;
00327 cf_log(llevDebug, PLUGIN_NAME ": adding %d NPC to map %s.\n", add, map->path);
00328
00329 while (add-- >= 0) {
00330 add_npc_to_zone(zone, map);
00331 }
00332 }
00333
00337 static void add_npc_to_random_map(void) {
00338 int count, test;
00339 mapstruct *list[50];
00340 int zones[50];
00341 count = 0;
00342
00343 cf_log(llevDebug, PLUGIN_NAME ": adding NPC to random map.\n");
00344
00345 for (test = 0; available_zones[test].count_points != -1 && count < 50; test++) {
00346 if ((list[count] = cf_map_has_been_loaded(available_zones[test].mapname)) && (list[count]->in_memory == MAP_IN_MEMORY)) {
00347 zones[count] = test;
00348 count++;
00349 }
00350 }
00351 if (!count)
00352 return;
00353
00354 test = RANDOM()%count;
00355 add_npc_to_point(&available_zones[zones[test]], list[test]);
00356 }
00357
00358 CF_PLUGIN void *citylife_globalEventListener(int *type, ...) {
00359 va_list args;
00360 static int rv = 0;
00361 mapstruct *map;
00362 int code;
00363
00364 va_start(args, type);
00365 code = va_arg(args, int);
00366
00367 rv = 0;
00368
00369 switch (code) {
00370 case EVENT_MAPLOAD:
00371 map = va_arg(args, mapstruct *);
00372 add_npcs_to_map(map);
00373 break;
00374
00375 case EVENT_CLOCK:
00376 if (RANDOM()%40 == 0)
00377 add_npc_to_random_map();
00378 }
00379 va_end(args);
00380
00381 return &rv;
00382 }
00383
00384 CF_PLUGIN int postInitPlugin(void) {
00385 cf_log(llevDebug, PLUGIN_VERSION " post init\n");
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 cf_system_register_global_event(EVENT_CLOCK, PLUGIN_NAME, citylife_globalEventListener);
00406 cf_system_register_global_event(EVENT_MAPLOAD, PLUGIN_NAME, citylife_globalEventListener);
00407
00408
00409
00410
00411 return 0;
00412 }
00413
00414 CF_PLUGIN void *eventListener(int *type, ...) {
00415 static int rv = 1;
00416 va_list args;
00417 char *buf;
00418 object *ground, *who, *activator, *third, *event;
00419 int fix;
00420 const char *value;
00421
00422 va_start(args, type);
00423
00424 who = va_arg(args, object *);
00425 activator = va_arg(args, object *);
00426 third = va_arg(args, object *);
00427 buf = va_arg(args, char *);
00428 fix = va_arg(args, int);
00429 event = va_arg(args, object *);
00430 va_end(args);
00431
00432
00433 if (RANDOM()%100 < 30) {
00434 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)) {
00435 if (ground->type == EXIT) {
00436 object *inv;
00437
00438 value = cf_object_get_key(who, FIRST_MOVE_KEY);
00439 if (strcmp(value, "1") == 0) {
00440 cf_object_set_key(who, FIRST_MOVE_KEY, "0", 1);
00441 break;
00442 }
00443
00444
00445 for (inv = cf_object_get_object_property(who, CFAPI_OBJECT_PROP_INVENTORY); inv; inv = cf_object_get_object_property(inv, CFAPI_OBJECT_PROP_OB_BELOW))
00446 cf_object_set_flag(inv, FLAG_NO_DROP, 1);
00447
00448 cf_log(llevDebug, PLUGIN_NAME ": NPC entering building.\n");
00449 cf_object_remove(who);
00450 cf_object_free(who);
00451 return &rv;
00452 }
00453 }
00454 }
00455
00456
00457 cf_object_move(who, 1+RANDOM()%8, NULL);
00458
00459 return &rv;
00460 }
00461
00462 CF_PLUGIN int closePlugin(void) {
00463 cf_log(llevDebug, PLUGIN_VERSION " closing\n");
00464 return 0;
00465 }