From 81518cae51ed11b62ab26ed0e2171e07b3beec6f Mon Sep 17 00:00:00 2001 From: div0 Date: Tue, 14 Oct 2008 08:30:18 +0000 Subject: [PATCH] experimental target_spawn entity that should be able to spawn anything git-svn-id: svn://svn.icculus.org/nexuiz/trunk@4743 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/server/defs.qh | 1 + data/qcsrc/server/g_world.qc | 5 + data/qcsrc/server/progs.src | 2 + data/qcsrc/server/target_spawn.qc | 189 ++++++++++++++++++++++++++++++ data/scripts/entities.def | 22 ++++ 5 files changed, 219 insertions(+) create mode 100644 data/qcsrc/server/target_spawn.qc diff --git a/data/qcsrc/server/defs.qh b/data/qcsrc/server/defs.qh index b69583eca..7d8b0c170 100644 --- a/data/qcsrc/server/defs.qh +++ b/data/qcsrc/server/defs.qh @@ -415,6 +415,7 @@ float q3acompat_machineshotgunswap; // database float ServerProgsDB; +float TemporaryDB; .float team_saved; diff --git a/data/qcsrc/server/g_world.qc b/data/qcsrc/server/g_world.qc index ab0034368..537f67bda 100644 --- a/data/qcsrc/server/g_world.qc +++ b/data/qcsrc/server/g_world.qc @@ -232,6 +232,8 @@ void spawnfunc_worldspawn (void) else ServerProgsDB = db_load("server.db"); + TemporaryDB = db_create(); + /* TODO sound pack system // initialize sound pack system @@ -2322,7 +2324,10 @@ void SV_Shutdown() Ban_SaveBans(); if(!sv_cheats) db_save(ServerProgsDB, "server.db"); + if(cvar("developer")) + db_save(TemporaryDB, "server-temp.db"); db_close(ServerProgsDB); + db_close(TemporaryDB); print("done!\n"); // tell the bot system the game is ending now bot_endgame(); diff --git a/data/qcsrc/server/progs.src b/data/qcsrc/server/progs.src index 1fcd0b331..ec768fe17 100644 --- a/data/qcsrc/server/progs.src +++ b/data/qcsrc/server/progs.src @@ -136,3 +136,5 @@ tturrets/include/turret_tturrets.qh scores.qc portals.qc + +target_spawn.qc diff --git a/data/qcsrc/server/target_spawn.qc b/data/qcsrc/server/target_spawn.qc new file mode 100644 index 000000000..d88fa22fa --- /dev/null +++ b/data/qcsrc/server/target_spawn.qc @@ -0,0 +1,189 @@ +// spawner entity +// "classname" "target_spawn" +// "message" "fieldname value fieldname value ..." +// "spawnflags" +// 1 = call the spawn function +// 2 = trigger on map load + +float target_spawn_initialized; +.void() target_spawn_spawnfunc; +float target_spawn_spawnfunc_field; +.entity target_spawn_activator; + +void target_spawn_use() +{ + float i, n, valuefieldpos, sPWNed; + entity e; + string key, value, valuefield, valueoffset; + entity valueent; + vector data, data2; + entity oldself; + entity oldactivator; + + e = spawn(); + n = tokenize_sane(self.message); + + sPWNed = FALSE; + + for(i = 0; i < n-1; i += 2) + { + key = argv(i); + value = argv(i+1); + data = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", key))); + if(data_y == 0) // undefined field, i.e., invalid type + { + print("target_spawn: invalid/unknown entity key ", key, " specified, ignored!\n"); + continue; + } + if(substring(value, 0, 1) == "$") + { + value = substring(value, 1, strlen(value) - 1); + if(substring(value, 0, 1) == "$") + { + // deferred replacement + // do nothing + // useful for creating target_spawns with this! + } + else + { + // replace me! + valuefieldpos = strstrofs(value, ".", 0); + valuefield = ""; + if(valuefieldpos != -1) + { + valuefield = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1); + value = substring(value, 0, valuefieldpos); + } + + valuefieldpos = strstrofs(value, "+", 0); + valueoffset = ""; + if(valuefieldpos != -1) + { + valueoffset = substring(valuefield, valuefieldpos + 1, strlen(value) - valuefieldpos - 1); + valuefield = substring(valuefield, 0, valuefieldpos); + } + + if(value == "self") + { + valueent = self; + value = ""; + } + else if(value == "activator") + { + valueent = activator; + value = ""; + } + else if(value == "pusher") + { + if(time < activator.pushltime) + valueent = activator.pusher; + else + valueent = world; + value = ""; + } + else if(value == "time") + { + valueent = world; + value = ftos(time); + } + else + { + print("target_spawn: invalid/unknown variable replacement ", value, " specified, ignored!\n"); + continue; + } + + if(valuefield == "") + { + if(value == "") + value = ftos(num_for_edict(valueent)); + } + else + { + if(value != "") + { + print("target_spawn: try to get a field of a non-entity, ignored!\n"); + continue; + } + data2 = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", valuefield))); + if(data2_y == 0) // undefined field, i.e., invalid type + { + print("target_spawn: invalid/unknown entity key replacement ", value, " specified, ignored!\n"); + continue; + } + value = getentityfieldstring(data2_x, valueent); + } + + if(valueoffset != "") + { + switch(data_y) + { + case FIELD_STRING: + value = strcat(value, valueoffset); + break; + case FIELD_FLOAT: + value = ftos(stof(value) + stof(valueoffset)); + break; + case FIELD_VECTOR: + value = vtos(stov(value) + stov(valueoffset)); + break; + default: + print("target_spawn: only string, float and vector fields can do calculations, calculation ignored!\n"); + break; + } + } + } + } + putentityfieldstring(data_x, e, value); + + if(key == "classname" && !sPWNed) + { + if(self.spawnflags & 1) + { + if(!e.target_spawn_spawnfunc) + putentityfieldstring(target_spawn_spawnfunc_field, e, strcat("spawnfunc_", value)); + + oldself = self; + oldactivator = activator; + + self = e; + activator = self.target_spawn_activator; + + self.target_spawn_spawnfunc(); + + self = oldself; + activator = oldactivator; + } + sPWNed = TRUE; + } + } +} + +void target_spawn_spawnfirst() +{ + activator = self.target_spawn_activator; + target_spawn_use(); +} + +void spawnfunc_target_spawn() +{ + if(!target_spawn_initialized) + { + float n, i; + string fn; + float ft; + + n = numentityfields(); + for(i = 0; i < n; ++i) + { + fn = entityfieldname(i); + ft = entityfieldtype(i); + db_put(TemporaryDB, strcat("/target_spawn/field/", fn), vtos(i * '1 0 0' + ft * '0 1 0' + '0 0 1')); + if(fn == "target_spawn_spawnfunc") + target_spawn_spawnfunc_field = i; + } + + target_spawn_initialized = 1; + } + if(self.spawnflags & 2) + InitializeEntity(self, target_spawn_spawnfirst, INITPRIO_LAST); +} diff --git a/data/scripts/entities.def b/data/scripts/entities.def index 2b0baa153..6c1e91ef7 100644 --- a/data/scripts/entities.def +++ b/data/scripts/entities.def @@ -1080,3 +1080,25 @@ AND: any items not listed will get removed, and none will get added OR: the player may keep items not listed ANDNOT: the items listed will get removed from the player */ + +/*QUAKED target_spawn (1 0 1) (-8 -8 -8) (8 8 8) SPAWNFUNC ONLOAD +Spawns an entity when triggered. +The entity field list is a single string of the form: +"field" "value" "field" "value" ... "classname" "item_bullets" ... "field" "value" +Field values can use various variable replacements: +$E +$E.field +$E.field+offset +where "E" can be self, activator and pusher. +Example is a Mario-style question mark block which could throw a new weapon_nex when activated like this: +{ +"classname" "target_spawn" +"message" "origin \"$self.origin+0 0 128\" velocity \"$activator.velocity+0 0 200\" owner $activator flags 65536 colormap $activator.colormap target_spawn_spawnfunc weapon_nex classname droppedweapon think thrown_wep_think nextthink $time+0.5" +} +-------- KEYS -------- +targetname: used to trigger this +message: entity field list +-------- SPAWNFLAGS -------- +SPAWNFUNC: call the spawn function when the "classname" key is mentioned in the fields list +ONLOAD: create a first entity on map load +*/ -- 2.39.2