/* War of the worlds, simulates a planet being at war with another planet by firing APC Warheads at them. Usage: [-i ] */ #include #include #include #include #include #include "../include/swserv-plugins.h" /* * Object Reference: * * Relates each fighter to a reference object. This is used to * check when a fighter has been destroyed (when it has become * garbage) and to respawn it. It also can be used to check if the * reference object has been destroyed (when it has become garbage) * and to no longer respawn a fighter. */ typedef struct { int obj_num, /* The object doing the firing */ tar_obj_num; /* The victim object */ } ObjRef; typedef struct { ObjRef **objref_list; int nobjrefs; time_t next_update, /* In seconds */ update_int; } Core; #define CORE(p) ((Core *)(p)) static void WOWUpdate(SWServContext *ctx); #define WEAPON_OPM_NAME "APC Warhead" #define WEAPON_DEF_DAMAGE_HULL 100.0 #define WEAPON_DEF_DAMAGE_SHIELDS 100.0 #define WOW_DEF_UPDATE_INVERVAL (1 * 60) /* In seconds */ #define USAGE_MESG "\ Usage: [-i ] [obj2_num] [tar_obj2_num] ..." #define ATOI(s) (((s) != NULL) ? atoi(s) : 0) #define ATOL(s) (((s) != NULL) ? atol(s) : 0) #define ATOF(s) (((s) != NULL) ? atof(s) : 0.0f) #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h))) #define STRLEN(s) (((s) != NULL) ? strlen(s) : 0) #define STRISEMPTY(s) (((s) != NULL) ? (*(s) == '\0') : TRUE) #ifndef PI # define PI 3.141592654 #endif /* * Fires an APC from the object to the target object. */ static void WOWUpdate(SWServContext *ctx) { Core *core = CORE(SWServGetData(ctx)); int i, obj_num, tar_obj_num, wep_obj_num, wep_opm_num = SWServOPMGetByName(ctx, WEAPON_OPM_NAME); xsw_object_struct *obj, *tar_obj, *wep_obj; ObjRef *objref; if(wep_opm_num < 0) { char *s = (char *)malloc(STRLEN(WEAPON_OPM_NAME) + 80); sprintf( s, "OPM `%s' not defined.\n", WEAPON_OPM_NAME ); SWServPrintError(ctx, s); free(s); return; } /* Iterate through the object references list */ for(i = 0; i < core->nobjrefs; i++) { objref = core->objref_list[i]; if(objref == NULL) continue; obj_num = objref->obj_num; obj = SWServObjectGetPointer(ctx, obj_num); tar_obj_num = objref->tar_obj_num; tar_obj = SWServObjectGetPointer(ctx, tar_obj_num); if((obj == NULL) || (tar_obj == NULL)) { /* Th objects no longer exists, so delete this object * reference */ free(objref); core->objref_list[i] = NULL; continue; } /* Create a new weapon */ wep_obj_num = SWServObjectCreate( ctx, SW_OBJ_TYPE_WEAPON ); wep_obj = SWServObjectGetPointer(ctx, wep_obj_num); if(wep_obj != NULL) { float heading = (0.5 * PI) - atan2( tar_obj->y - obj->y, tar_obj->x - obj->x ); while(heading > (2 * PI)) heading -= (2 * PI); while(heading < (0 * PI)) heading += (2 * PI); SWServOPMModelObject(ctx, wep_opm_num, wep_obj_num); SWServWeaponSetFlags( ctx, wep_obj_num, SW_WEP_FLAG_DESTROYABLE ); SWServWeaponSetFlags( ctx, wep_obj_num, SW_WEP_FLAG_SHOCKWAVE_HIT ); wep_obj->owner = obj_num; wep_obj->sect_x = obj->sect_x; wep_obj->sect_y = obj->sect_y; wep_obj->sect_z = obj->sect_z; wep_obj->x = obj->x; wep_obj->y = obj->y; wep_obj->z = obj->z; wep_obj->heading = (float)heading; wep_obj->hp_max = WEAPON_DEF_DAMAGE_HULL; wep_obj->hp = WEAPON_DEF_DAMAGE_HULL; wep_obj->power_max = WEAPON_DEF_DAMAGE_SHIELDS; wep_obj->power = WEAPON_DEF_DAMAGE_SHIELDS; wep_obj->birth_time = SWServCurrentTimeMS(ctx); /* strncpy(wep_obj->name, WEAPON_OPM_NAME, sizeof(obj->name)); wep_obj->name[sizeof(wep_obj->name) - 1] = '\0'; */ strncpy(wep_obj->empire, obj->empire, sizeof(obj->empire)); wep_obj->empire[sizeof(wep_obj->empire) - 1] = '\0'; SWServObjectSyncConnections(ctx, wep_obj_num, 1); } } } /* * SWServ Plugin destroy notify. */ SWPLUGIN_DESTROY_NOTIFY_FUNCRTN SWPLUGIN_DESTROY_NOTIFY_FUNC( int reason, int destroyed_obj_num, int destroyer_obj_num, int destroyer_obj_owner_num, SWServContext *ctx ) { Core *core = CORE(SWServGetData(ctx)); int i; ObjRef *objref; if(core == NULL) return; /* Iterate through the object references list */ for(i = 0; i < core->nobjrefs; i++) { objref = core->objref_list[i]; if(objref == NULL) continue; /* This object destroyed? */ if(objref->obj_num == destroyed_obj_num) { objref->obj_num = -1; break; } /* Target destroyed? */ if(objref->tar_obj_num == destroyed_obj_num) { objref->tar_obj_num = -1; break; } } } /* * SWServ Plugin initialize. */ SWPLUGIN_INIT_FUNCRTN SWPLUGIN_INIT_FUNC( int argc, char **argv, int con_num, SWServContext *ctx ) { int i; const char *arg; Core *core = CORE(calloc(1, sizeof(Core))); if(core == NULL) return(1); core->objref_list = NULL; core->nobjrefs = 0; core->update_int = WOW_DEF_UPDATE_INVERVAL; core->next_update = SWServCurrentTimeSeconds(ctx); SWServSetData(ctx, core); for(i = 0; i < argc; i++) { arg = argv[i]; if(arg == NULL) continue; if(!strcasecmp(arg, "--help") || !strcasecmp(arg, "-help") || !strcasecmp(arg, "--h") || !strcasecmp(arg, "-h") ) { if(con_num > -1) SWServConNotify( ctx, con_num, USAGE_MESG ); else SWServPrint( ctx, USAGE_MESG "\n" ); free(core); return(1); } else if(!strcasecmp(arg, "--interval") || !strcasecmp(arg, "-interval") || !strcasecmp(arg, "--int") || !strcasecmp(arg, "-int") || !strcasecmp(arg, "-i") ) { /* In seconds */ i++; if(i < argc) core->update_int = MAX(atol(argv[i]), 0l); } else { /* All else assume object number pair */ int n; const int obj_num = ATOI( (*arg == '#') ? (arg + 1) : arg ); ObjRef *objref = (ObjRef *)calloc( 1, sizeof(ObjRef) ); objref->obj_num = obj_num; objref->tar_obj_num = -1; n = core->nobjrefs; core->nobjrefs = n + 1; core->objref_list = (ObjRef **)realloc( core->objref_list, core->nobjrefs * sizeof(ObjRef *) ); core->objref_list[n] = objref; i++; if(i < argc) { arg = argv[i]; objref->tar_obj_num = ATOI( (*arg == '#') ? (arg + 1) : arg ); } } } /* No reference objects spcified? */ if(core->nobjrefs <= 0) { if(con_num > -1) SWServConNotify( ctx, con_num, USAGE_MESG ); else SWServPrintError( ctx, USAGE_MESG "\n" ); free(core); return(1); } return(0); } /* * SWServ Plugin manage. */ SWPLUGIN_MANAGE_FUNCRTN SWPLUGIN_MANAGE_FUNC( SWServContext *ctx ) { Core *core = CORE(SWServGetData(ctx)); const time_t t = SWServCurrentTimeSeconds(ctx); if(core == NULL) return(1); /* Time to update? */ if(core->next_update <= t) { WOWUpdate(ctx); core->next_update = t + core->update_int; } return(0); } /* * SWServ Plugin shutdown. */ SWPLUGIN_SHUTDOWN_FUNCRTN SWPLUGIN_SHUTDOWN_FUNC( SWServContext *ctx ) { Core *core = CORE(SWServGetData(ctx)); int i; ObjRef *objref; if(core == NULL) return; for(i = 0; i < core->nobjrefs; i++) { objref = core->objref_list[i]; if(objref == NULL) continue; free(objref); } free(core->objref_list); free(core); SWServSetData(ctx, NULL); }