diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
| commit | c068f22329d5cc722622a2183bbb22eef2093df7 (patch) | |
| tree | 12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec/part_def.cpp | |
| download | openparsec-main.tar.xz openparsec-main.zip | |
Diffstat (limited to 'src/parsec/part_def.cpp')
| -rw-r--r-- | src/parsec/part_def.cpp | 1241 |
1 files changed, 1241 insertions, 0 deletions
diff --git a/src/parsec/part_def.cpp b/src/parsec/part_def.cpp new file mode 100644 index 0000000..2493492 --- /dev/null +++ b/src/parsec/part_def.cpp @@ -0,0 +1,1241 @@ +/* + * PARSEC - Particle Definitions + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:36 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger <msh@parsec.org> 1998-2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// particle types +#include "parttype.h" + +// local module header +#include "part_def.h" + +// proprietary module headers +#include "con_arg.h" +#include "con_com.h" +#include "con_main.h" +#include "obj_ctrl.h" +#include "part_api.h" + +//FIXME: [CLEMENS] split this into game and engine modules + +// generic string paste area +#define PASTE_STR_LEN 255 +static char paste_str[ PASTE_STR_LEN + 1 ]; + + +// names of available particle definitions ------------------------------------ +// +struct pdefnames_s { + + const char *pdefname; + pdef_s *(*pdeffunction)(); +}; + +pdefnames_s s_pdefnames[] = { + + { "plight01", PDEF_plight01 }, + { "psmoke01", PDEF_psmoke01 }, + { "psmoke02", PDEF_psmoke02 }, + { "pflare01", PDEF_pflare01 }, + { "pflare02", PDEF_pflare02 }, + { "pflare03", PDEF_pflare03 }, + { "pflare04", PDEF_pflare04 }, + { "pflare05", PDEF_pflare05 }, + { "pflare06", PDEF_pflare06 }, + { "stargate", PDEF_stargate }, + { "explode1", PDEF_explode1 }, + { "expwave1", PDEF_expwave1 }, + { "misglow1", PDEF_misglow1 }, + { "extragen", PDEF_extragen }, + + { NULL, NULL } +}; + +// make table substitution possible +pdefnames_s *pdefnames = s_pdefnames; + +// macros to retrieve names internally +#define PLIGHT01 pdefnames[0].pdefname +#define PSMOKE01 pdefnames[1].pdefname +#define PSMOKE02 pdefnames[2].pdefname +#define PFLARE01 pdefnames[3].pdefname +#define PFLARE02 pdefnames[4].pdefname +#define PFLARE03 pdefnames[5].pdefname +#define PFLARE04 pdefnames[6].pdefname +#define PFLARE05 pdefnames[7].pdefname +#define PFLARE06 pdefnames[8].pdefname +#define STARGATE pdefnames[9].pdefname +#define EXPLODE1 pdefnames[10].pdefname +#define EXPWAVE1 pdefnames[11].pdefname +#define MISGLOW1 pdefnames[12].pdefname +#define EXTRAGEN pdefnames[13].pdefname + + +// fetch particle definition by name ------------------------------------------ +// +pdef_s *PDEF_FetchByName( char *name ) +{ + //NOTE: + // this function should not be confused with + // PRT_AcquireParticleDefinition(). the API function + // is only able to return already registered pdefs, + // whereas this function will register the pdef + // of the specified name if not already done. + + // look up name of particle definition and + // call corresponding definition function + for ( pdefnames_s *scan = pdefnames; scan->pdefname; scan++ ) + if ( strcmp( name, scan->pdefname ) == 0 ) + return (*scan->pdeffunction)(); + + // name not found + return NULL; +} + + +// particle animation tables for "plight01" ----------------------------------- +// +const char *plight01_texnames[] = { + + "imp_001", + "imp_003", + "imp_005", + "imp_007", + "imp_009", + "imp_011", + "imp_013", + "imp_015", + "imp_017", + "imp_019", + "imp_021", + "imp_023", + "imp_025", +// "imp_027", +// "imp_029", +}; + +int plight01_texframes = CALC_NUM_ARRAY_ENTRIES( plight01_texnames ); + + +// fetch particle definition for "plight01" ----------------------------------- +// +pdef_s *PDEF_plight01() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( PLIGHT01, &pdefid ); + if ( pdef == NULL ) { + + // alloc temporary table mem + ptexreg_s *texinfo = (ptexreg_s *) ALLOCMEM( sizeof( ptexreg_s ) * plight01_texframes ); + if ( texinfo == NULL ) + return NULL; + + // init temporary table mem + for ( int fid = 0; fid < plight01_texframes; fid++ ) { + texinfo[ fid ].deltatime = 30; + texinfo[ fid ].texname = (char *) plight01_texnames[ fid ]; + } + + // init registration info + pdefreg_s pdefreg; + pdefreg.texinfo = texinfo; + pdefreg.textabsize = plight01_texframes; + pdefreg.texstart = 0; + pdefreg.texrep = 5; + pdefreg.texend = plight01_texframes - 1; + pdefreg.xfoinfo = NULL; + pdefreg.xfotabsize = 0; + + // register particle definition + pdef = PRT_RegisterParticleDefinition( PLIGHT01, &pdefreg, FALSE ); + + // free temporary table mem + FREEMEM( texinfo ); + } + } + return pdef; +} + + +// particle animation tables for "psmoke01" ----------------------------------- +// +const char *psmoke01_texnames[] = { + + "smoke001", + "smoke003", + "smoke005", + "smoke007", + "smoke009", + "smoke011", + "smoke013", + "smoke015", + "smoke017", + "smoke019", + "smoke021", + "smoke023", +}; + +int psmoke01_texframes = CALC_NUM_ARRAY_ENTRIES( psmoke01_texnames ); + + +// fetch particle definition for "psmoke01" ----------------------------------- +// +pdef_s *PDEF_psmoke01() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( PSMOKE01, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterOneShotTexParticle( + PSMOKE01, psmoke01_texframes, psmoke01_texnames, 20, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "psmoke02" ----------------------------------- +// +//char *psmoke02_texnames[] = { +//}; + +//int psmoke02_texframes = CALC_NUM_ARRAY_ENTRIES( psmoke02_texnames ); + + +// fetch particle definition for "psmoke02" ----------------------------------- +// +pdef_s *PDEF_psmoke02() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( PSMOKE02, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterOneShotTexParticle( + PSMOKE02, psmoke01_texframes, psmoke01_texnames, 80, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "pflare01" ----------------------------------- +// +const char *pflare01_texnames[] = { + + "eff10001", +// "eff10003", +// "eff10005", +// "eff10007", +// "eff10009", +// "eff10011", +// "eff10013", +// "eff10015", +// "eff10017", +// "eff10019", +// "eff10021", +// "eff10023", +// "eff10025", +// "eff10027", +// "eff10029", +}; + +int pflare01_texframes = CALC_NUM_ARRAY_ENTRIES( pflare01_texnames ); + + +// fetch particle definition for "pflare01" ----------------------------------- +// +pdef_s *PDEF_pflare01() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( PFLARE01, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterLoopTexParticle( + PFLARE01, pflare01_texframes, pflare01_texnames, 30, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "pflare02" ----------------------------------- +// +const char *pflare02_texnames[] = { + + "eff20001", +// "eff20003", +// "eff20005", +// "eff20007", +// "eff20009", +// "eff20011", +// "eff20013", +// "eff20015", +// "eff20017", +// "eff20019", +// "eff20021", +// "eff20023", +// "eff20025", +// "eff20027", +// "eff20029", +}; + +int pflare02_texframes = CALC_NUM_ARRAY_ENTRIES( pflare02_texnames ); + + +// fetch particle definition for "pflare02" ----------------------------------- +// +pdef_s *PDEF_pflare02() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( PFLARE02, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterLoopTexParticle( + PFLARE02, pflare02_texframes, pflare02_texnames, 30, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "pflare03" ----------------------------------- +// +const char *pflare03_texnames[] = { + +// "eff30001", +// "eff30003", +// "eff30005", +// "eff30007", +// "eff30009", +// "eff30011", +// "eff30013", + "eff30015", +// "eff30017", + "eff30019", +// "eff30021", +// "eff30023", +// "eff30025", +// "eff30027", + "eff30029", +}; + +int pflare03_texframes = CALC_NUM_ARRAY_ENTRIES( pflare03_texnames ); + + +// fetch particle definition for "pflare03" ----------------------------------- +// +pdef_s *PDEF_pflare03() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( PFLARE03, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterLoopTexParticle( + PFLARE03, pflare03_texframes, pflare03_texnames, 30, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "pflare04" ----------------------------------- +// +const char *pflare04_texnames[] = { + + "eff40001", +// "eff40003", +// "eff40005", +// "eff40007", +// "eff40009", +// "eff40011", +// "eff40013", +// "eff40015", +// "eff40017", +// "eff40019", +// "eff40021", +// "eff40023", +// "eff40025", +// "eff40027", +// "eff40029", +}; + +int pflare04_texframes = CALC_NUM_ARRAY_ENTRIES( pflare04_texnames ); + + +// fetch particle definition for "pflare04" ----------------------------------- +// +pdef_s *PDEF_pflare04() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( PFLARE04, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterLoopTexParticle( + PFLARE04, pflare04_texframes, pflare04_texnames, 30, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "pflare05" ----------------------------------- +// +const char *pflare05_texnames[] = { + + "eff50001", +// "eff50003", +// "eff50005", +// "eff50007", +// "eff50009", +// "eff50011", +// "eff50013", +// "eff50015", +// "eff50017", +// "eff50019", +// "eff50021", +// "eff50023", +// "eff50025", +// "eff50027", +// "eff50029", +}; + +int pflare05_texframes = CALC_NUM_ARRAY_ENTRIES( pflare05_texnames ); + + +// fetch particle definition for "pflare05" ----------------------------------- +// +pdef_s *PDEF_pflare05() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( PFLARE05, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterLoopTexParticle( + PFLARE05, pflare05_texframes, pflare05_texnames, 30, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "pflare06" ----------------------------------- +// +const char *pflare06_texnames[] = { + + "helix001", +}; + +int pflare06_texframes = CALC_NUM_ARRAY_ENTRIES( pflare06_texnames ); + + +// fetch particle definition for "pflare06" ----------------------------------- +// +pdef_s *PDEF_pflare06() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( PFLARE06, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterLoopTexParticle( + PFLARE06, pflare06_texframes, pflare06_texnames, 30, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "stargate" ----------------------------------- +// +const char *stargate_texnames[] = { + + "gate_001", + "gate_003", + "gate_005", + "gate_007", + "gate_009", + "gate_011", + "gate_013", + "gate_015", + "gate_017", + "gate_019", + "gate_021", + "gate_023", + "gate_025", + "gate_027", + "gate_029", + "gate_031", + "gate_033", + "gate_035", + "gate_037", + "gate_039", + "gate_041", + "gate_043", + "gate_045", + "gate_047", + "gate_049", + "gate_051", + "gate_053", + "gate_055", + "gate_057", + "gate_058", + "gate_059", + "gate_060", + "gate_000", +}; + +int stargate_texframes = CALC_NUM_ARRAY_ENTRIES( stargate_texnames ); + + +// fetch particle definition for "stargate" ----------------------------------- +// +pdef_s *PDEF_stargate() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( STARGATE, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterOneShotTexParticle( + STARGATE, stargate_texframes, stargate_texnames, 40, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "explode1" ----------------------------------- +// +const char *explode1_texnames[] = { + + "expl_001", + "expl_002", + "expl_003", + "expl_004", + "expl_005", + "expl_006", + "expl_007", + "expl_008", + "expl_009", + "expl_010", + "expl_011", + "expl_012", + "expl_013", + "expl_014", + "expl_015", + "expl_016", + "expl_017", + "expl_018", + "expl_019", + "expl_020", + "expl_021", + "expl_022", + "expl_023", + "expl_024", + "expl_025", + "expl_026", + "expl_027", + "expl_028", + "expl_029", + "expl_030", + "expl_031", +}; + +int explode1_texframes = CALC_NUM_ARRAY_ENTRIES( explode1_texnames ); + + +// fetch particle definition for "explode1" ----------------------------------- +// +pdef_s *PDEF_explode1() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( EXPLODE1, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterOneShotTexParticle( + EXPLODE1, explode1_texframes, explode1_texnames, 10, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "expwave1" ----------------------------------- +// +const char *expwave1_texnames[] = { + + "swv_001", + "swv_003", + "swv_005", + "swv_007", + "swv_009", + "swv_011", + "swv_013", + "swv_015", + "swv_017", + "swv_019", + "swv_021", + "swv_023", + "swv_025", +}; + +int expwave1_texframes = CALC_NUM_ARRAY_ENTRIES( expwave1_texnames ); + + +// fetch particle definition for "expwave1" ----------------------------------- +// +pdef_s *PDEF_expwave1() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( EXPWAVE1, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterLoopTexParticle( + EXPWAVE1, expwave1_texframes, expwave1_texnames, 30, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "misglow1" ----------------------------------- +// +const char *misglow1_texnames[] = { + + "glow06", +}; + +int misglow1_texframes = CALC_NUM_ARRAY_ENTRIES( misglow1_texnames ); + + +// fetch particle definition for "misglow1" ----------------------------------- +// +pdef_s *PDEF_misglow1() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( MISGLOW1, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterLoopTexParticle( + MISGLOW1, misglow1_texframes, misglow1_texnames, 30, FALSE ); + } + } + return pdef; +} + + +// particle animation tables for "extragen" ----------------------------------- +// +const char *extragen_texnames[] = { + + "eg01_01a", + "eg01_02a", + "eg01_03a", + "eg01_04a", + "eg01_05a", + "eg01_06a", + "eg01_07a", + "eg01_08a", + "eg01_09a", + "eg01_10a", + "eg01_11a", + "eg01_12a", + "eg01_13a", + "eg01_14a", + "eg01_15a", +}; + +int extragen_texframes = CALC_NUM_ARRAY_ENTRIES( extragen_texnames ); + + +// fetch particle definition for "extragen" ----------------------------------- +// +pdef_s *PDEF_extragen() +{ + pdef_s *pdef; + static int pdefid = -1; + + if ( pdefid != -1 ) { + pdef = PRT_AcquireParticleDefinitionById( pdefid ); + } else { + // try to acquire pdef by name + pdef = PRT_AcquireParticleDefinition( EXTRAGEN, &pdefid ); + if ( pdef == NULL ) { + // register particle definition + pdef = PRT_RegisterOneShotTexParticle( + EXTRAGEN, extragen_texframes, extragen_texnames, 40, FALSE ); + } + } + return pdef; +} + + +// key table for pdef registration via console command ------------------------ +// +key_value_s pdef_key_value[] = { + + { "base", NULL, KEYVALFLAG_MANDATORY }, + { "len", NULL, KEYVALFLAG_MANDATORY }, + { "dig", NULL, KEYVALFLAG_NONE }, + { "tab", NULL, KEYVALFLAG_PARENTHESIZE }, + { "bgn", NULL, KEYVALFLAG_NONE }, + { "rep", NULL, KEYVALFLAG_NONE }, + { "end", NULL, KEYVALFLAG_NONE }, +//TODO: + { "xfolen", NULL, KEYVALFLAG_IGNORE }, + { "xfotab", NULL, KEYVALFLAG_IGNORE | KEYVALFLAG_PARENTHESIZE }, + { "xfobgn", NULL, KEYVALFLAG_IGNORE }, + { "xforep", NULL, KEYVALFLAG_IGNORE }, + { "xfoend", NULL, KEYVALFLAG_IGNORE }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_PDEF_TEXNAME, + KEY_PDEF_TEXLEN, + KEY_PDEF_TEXDIG, + KEY_PDEF_TEXTAB, + KEY_PDEF_TEXBGN, + KEY_PDEF_TEXREP, + KEY_PDEF_TEXEND, + + KEY_PDEF_XFOLEN, + KEY_PDEF_XFOTAB, + KEY_PDEF_XFOBGN, + KEY_PDEF_XFOREP, + KEY_PDEF_XFOEND +}; + +key_value_s pdef_textab_key_value[] = { + + { "base", NULL, KEYVALFLAG_NONE }, + { "stride", NULL, KEYVALFLAG_NONE }, + { "frm", NULL, KEYVALFLAG_PARENTHESIZE }, + + { "t", NULL, KEYVALFLAG_NONE }, + { "tl", NULL, KEYVALFLAG_PARENTHESIZE }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_PDEF_TEXTAB_FSTART, + KEY_PDEF_TEXTAB_FSTRIDE, + KEY_PDEF_TEXTAB_FLIST, + + KEY_PDEF_TEXTAB_TEQUI, + KEY_PDEF_TEXTAB_TLIST +}; + + +// console command for registering new particle definition ("pdef") ----------- +// +PRIVATE +int Cmd_PDEF( char *pdefstr ) +{ + //NOTE: + //CONCOM: + // pdef_command ::= 'pdef' <name> <texanispec> [<xfoanispec>] + // name ::= "may be parenthesized () to include whitespace" + // texanispec ::= <basename> <tablen> [<basedig>] [<textab>] [<textabctrl>] + // basename ::= 'base' <name> + // tablen ::= 'len' <int> + // basedig ::= 'dig' '1' | '2' | '3' | '4' + // textab ::= 'tab' '(' <texframespec> <textimespec> ')' + // texframespec ::= ( ['base' <int>] ['stride' <int>] ) | ['frm' '(' <intlist> ')'] + // textimespec ::= ['t' <int>] | ['tl' '(' <intlist> ')'] + // textabctrl ::= ['bgn' <int>] ['rep' <int>] ['end' <int>] + // xfoanispec ::= 'xfolen' <int> ['xfotab' <xfotab>] [<xfotabctrl>] + // xfotab ::= '(' ')' + // xfotabctrl ::= ['xfobgn' <int>] ['xforep' <int>] ['xfoend' <int>] + // intlist ::= [<intlist>] <int> + + ASSERT( pdefstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( pdefstr ); + + // create pointer to list of parameters (first is always the name) + char *pdefname = strtok( pdefstr, " " ); + if ( pdefname == NULL ) { + CON_AddLine( "name of pdef must be specified." ); + return TRUE; + } + + // allow name to be parenthesized to include whitespace + pdefname = GetParenthesizedName( pdefname ); + if ( pdefname == NULL ) { + CON_AddLine( "pdef name invalid." ); + return TRUE; + } + + // scan out all values to texture keys + if ( !ScanKeyValuePairs( pdef_key_value, NULL ) ) + return TRUE; + + // defaults + int texlen = -1; // missing + int texbgn = 0; + int texrep = 0; + int texend = -1; // missing + + int invalid; + invalid = ( ScanKeyValueInt( &pdef_key_value[ KEY_PDEF_TEXLEN ], &texlen ) < 0 ); + invalid += ( ScanKeyValueInt( &pdef_key_value[ KEY_PDEF_TEXBGN ], &texbgn ) < 0 ); + invalid += ( ScanKeyValueInt( &pdef_key_value[ KEY_PDEF_TEXREP ], &texrep ) < 0 ); + invalid += ( ScanKeyValueInt( &pdef_key_value[ KEY_PDEF_TEXEND ], &texend ) < 0 ); + + if ( invalid || ( texlen < 1 ) ) { + CON_AddLine( "invalid integer parameter." ); + return TRUE; + } + if ( ( texbgn < 0 ) || ( texbgn >= texlen ) || ( texend >= texlen ) || + ( texrep < 0 ) || ( texrep >= texlen ) ) { + CON_AddLine( "tabctrl range error." ); + return TRUE; + } + if ( texend < 0 ) { + // default if missing + texend = texlen - 1; + } + + // fetch base name for texture (enumeration will be appended automatically) + char *basestr = pdef_key_value[ KEY_PDEF_TEXNAME ].value; + ASSERT( basestr != NULL ); + int baselen = strlen( basestr ); + + // fetch number of name enum digits + int basedig = 3; + if ( pdef_key_value[ KEY_PDEF_TEXDIG ].value != NULL ) { + if ( ScanKeyValueInt( &pdef_key_value[ KEY_PDEF_TEXDIG ], &basedig ) < 0 ) { + CON_AddLine( "digit spec invalid." ); + return TRUE; + } + if ( ( basedig < 1 ) || ( basedig > 4 ) ) { + CON_AddLine( "only 1, 2, 3, or 4 digits allowed." ); + return TRUE; + } + } + + // alloc temporary table mem + char *tempmem = (char *) ALLOCMEM( texlen * sizeof( ptexreg_s ) + + texlen * sizeof( int ) * 2 + + texlen * ( baselen + basedig + 1 ) ); + if ( tempmem == NULL ) + return FALSE; + ptexreg_s * texinfo = (ptexreg_s *) tempmem; + int * tilist1 = (int *) ( tempmem + sizeof( ptexreg_s ) * texlen ); + int * tilist2 = tilist1 + texlen; + char * txnames = (char *) ( tilist2 + texlen ); + + // default values if no textab + int fstart = 0; + int fstride = 1; + int tequi = 30; + int *enumlist = NULL; + int *tdeltalist = NULL; + + // parse textab if supplied + char *textabstr = pdef_key_value[ KEY_PDEF_TEXTAB ].value; + if ( textabstr != NULL ) { + + if ( !ScanKeyValuePairs( pdef_textab_key_value, textabstr ) ) { + FREEMEM( tempmem ); + return TRUE; + } + + invalid = ( ScanKeyValueInt( &pdef_textab_key_value[ KEY_PDEF_TEXTAB_FSTART ], &fstart ) < 0 ); + invalid += ( ScanKeyValueInt( &pdef_textab_key_value[ KEY_PDEF_TEXTAB_FSTRIDE ], &fstride ) < 0 ); + invalid += ( ScanKeyValueInt( &pdef_textab_key_value[ KEY_PDEF_TEXTAB_TEQUI ], &tequi ) < 0 ); + + if ( invalid || ( fstart < 0 ) || ( tequi < 1 ) ) { + CON_AddLine( "invalid integer parameter." ); + FREEMEM( tempmem ); + return TRUE; + } + if ( ( fstart + fstride * ( texlen - 1 ) ) < 0 ) { + CON_AddLine( "stride invalid." ); + FREEMEM( tempmem ); + return TRUE; + } + + //NOTE: + // stride is allowed to be negative in order to make + // playback of textures in reversed order possible. + // (without listing all frames explicitly, which, of + // course, is able to achieve the same result.) + + // check for enumeration list + if ( pdef_textab_key_value[ KEY_PDEF_TEXTAB_FLIST ].value != NULL ) { + enumlist = tilist1; + if ( !ScanKeyValueIntList( &pdef_textab_key_value[ KEY_PDEF_TEXTAB_FLIST ], enumlist, texlen, texlen ) ) { + FREEMEM( tempmem ); + return TRUE; + } + } + + // check for timedelta list + if ( pdef_textab_key_value[ KEY_PDEF_TEXTAB_TLIST ].value != NULL ) { + tdeltalist = tilist2; + if ( !ScanKeyValueIntList( &pdef_textab_key_value[ KEY_PDEF_TEXTAB_TLIST ], tdeltalist, texlen, texlen ) ) { + FREEMEM( tempmem ); + return TRUE; + } + } + } + + // init temporary table mem + if ( texlen == 1 ) { + + // use base name as is for single frame + texinfo[ 0 ].texname = basestr; + texinfo[ 0 ].deltatime = tdeltalist ? *tdeltalist : tequi; + + } else { + + // automatically append frame numbers to base name + for ( int fid = 0; fid < texlen; fid++ ) { + + strcpy( txnames, basestr ); + + int frameno; + if ( enumlist != NULL ) { + frameno = *enumlist; + enumlist++; + } else { + frameno = fstart; + fstart += fstride; + } + + for ( int dpos = basedig - 1; dpos >= 0; dpos-- ) { + txnames[ baselen + dpos ] = ( frameno % 10 ) + '0'; + frameno /= 10; + } + txnames[ baselen + basedig ] = 0; + + texinfo[ fid ].texname = txnames; + texinfo[ fid ].deltatime = tdeltalist ? *tdeltalist++ : tequi; + + txnames += baselen + basedig + 1; + } + } + + // init registration info + pdefreg_s pdefreg; + pdefreg.texinfo = texinfo; + pdefreg.textabsize = texlen; + pdefreg.texstart = texbgn; + pdefreg.texrep = texrep; + pdefreg.texend = texend; + pdefreg.xfoinfo = NULL; + pdefreg.xfotabsize = 0; + + // do registration + pdef_s *pdef = PRT_RegisterParticleDefinition( pdefname, &pdefreg, TRUE ); + + // free temporary table mem + FREEMEM( tempmem ); + + // pdef registration may fail (e.g., texture name not found) + if ( pdef == NULL ) { + CON_AddLine( "could not register pdef." ); + } + + return TRUE; +} + + +// key table for pattach command ---------------------------------------------- +// +key_value_s pattach_key_value[] = { + + { "ship", NULL, KEYVALFLAG_MANDATORY }, + { "origin", NULL, KEYVALFLAG_MANDATORY | KEYVALFLAG_PARENTHESIZE }, + { "size", NULL, KEYVALFLAG_NONE }, + { "type", NULL, KEYVALFLAG_NONE }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_PATTACH_SHIPID, + KEY_PATTACH_ORIGIN, + KEY_PATTACH_REFZ, + KEY_PATTACH_TYPE +}; + + +// console command for attaching a particle to a ship ("pattach") ------------- +// +PRIVATE +int Cmd_PATTACH( char *attachstr ) +{ + //NOTE: + //CONCOM: + // pattach_command ::= 'pattach' <pdefname> <shipspec> <origin> [<ref_z>] [<type>] + // shipspec ::= 'ship' 'local' | 'target' + // origin ::= 'origin' '(' <float> <float> <float> ')' + // ref_z ::= 'size' <float> + // type ::= 'normal' | 'flare' | 'light' + + ASSERT( attachstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( attachstr ); + + // create pointer to name of pdef to use + char *pdefname = strtok( attachstr, " " ); + if ( pdefname == NULL ) { + CON_AddLine( "name of pdef must be specified." ); + return TRUE; + } + + // allow name to be parenthesized to include whitespace + pdefname = GetParenthesizedName( pdefname ); + if ( pdefname == NULL ) { + CON_AddLine( "pdef name invalid." ); + return TRUE; + } + + // scan out all values to keys + if ( !ScanKeyValuePairs( pattach_key_value, NULL ) ) + return TRUE; + + // default is local ship + ShipObject *baseship = MyShip; + + char *shipspec = pattach_key_value[ KEY_PATTACH_SHIPID ].value; + if ( shipspec != NULL ) { + + if ( strcmp( shipspec, "target" ) == 0 ) { + + if ( TargetObjNumber != TARGETID_NO_TARGET ) { + + // search for target + GenObject *scan = FetchFirstShip(); + while ( ( scan != NULL ) && ( scan->HostObjNumber != TargetObjNumber ) ) + scan = scan->NextObj; + if ( scan == NULL ) { + ASSERT( 0 ); + CON_AddLine( "target not found." ); + return TRUE; + } + baseship = (ShipObject *) scan; + + } else { + CON_AddLine( "no target selected." ); + return TRUE; + } + + } else if ( strcmp( shipspec, "local" ) != 0 ) { + + //TODO: + // allow numerical ship ids. + + CON_AddLine( "shipid invalid." ); + return TRUE; + } + } + + // determine origin (mandatory) + Vertex3 origin; + if ( pattach_key_value[ KEY_PATTACH_ORIGIN ].value != NULL ) { + + float locspec[ 3 ]; + if ( !ScanKeyValueFloatList( &pattach_key_value[ KEY_PATTACH_ORIGIN ], locspec, 3, 3 ) ) { + CON_AddLine( "origin invalid." ); + return TRUE; + } + + origin.X = FLOAT_TO_GEOMV( locspec[ 0 ] ); + origin.Y = FLOAT_TO_GEOMV( locspec[ 1 ] ); + origin.Z = FLOAT_TO_GEOMV( locspec[ 2 ] ); + } + + // fetch pdef + pdef_s *pdef = PRT_AcquireParticleDefinition( pdefname, NULL ); + if ( pdef == NULL ) { + CON_AddLine( "pdef invalid." ); + return TRUE; + } + + // determine size + float ref_z = 10.0f; + if ( pattach_key_value[ KEY_PATTACH_REFZ ].value != NULL ) { + if ( ScanKeyValueFloat( &pattach_key_value[ KEY_PATTACH_REFZ ], &ref_z ) < 0 ) { + CON_AddLine( "refz invalid." ); + return TRUE; + } + } + + // determine particle type + dword rendflags = PART_REND_NONE; + char *typestr = pattach_key_value[ KEY_PATTACH_TYPE ].value; + if ( typestr != NULL ) { + if ( strcmp( typestr, "flare" ) == 0 ) { + rendflags = PART_REND_POINTVIS | PART_REND_NODEPTHCMP | PART_REND_NODEPTHSCALE; + } else if ( strcmp( typestr, "light" ) == 0 ) { + rendflags = PART_REND_POINTVIS | PART_REND_NODEPTHCMP; + } else if ( strcmp( typestr, "normal" ) != 0 ) { + CON_AddLine( "type invalid." ); + return TRUE; + } + } + + // basic attributes + int bitmap = ( iter_texrgba | iter_specularadd ) | rendflags; + int color = 0; + + // create pextinfo + pextinfo_s extinfo; + PRT_InitParticleExtInfo( &extinfo, pdef, NULL, NULL ); + + particle_s particle; + PRT_InitParticle( particle, bitmap, color, PRT_NO_SIZEBOUND, + ref_z, &origin, NULL, INFINITE_LIFETIME, + LocalPlayerId, //TODO: GetObjectOwner( shippo ) + &extinfo ); + + // attach particle to ship + if ( PRT_CreateGenObjectParticle( particle, baseship, NULL ) == NULL ) { + CON_AddLine( "could not create or attach particle." ); + } + + return TRUE; +} + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE( PART_DEF ) +{ + user_command_s regcom; + memset( ®com, 0, sizeof( user_command_s ) ); + + // register "pdef" command + regcom.command = "pdef"; + regcom.numparams = 1; + regcom.execute = Cmd_PDEF; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + + // register "pattach" command + regcom.command = "pattach"; + regcom.numparams = 1; + regcom.execute = Cmd_PATTACH; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); +} + + + |
