Subversion Repositories eduke32

Rev

Rev 8478 | Rev 8519 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
//-------------------------------------------------------------------------
2
/*
1652 terminx 3
Copyright (C) 2010 EDuke32 developers and contributors
5 Plagman 4
 
1652 terminx 5
This file is part of EDuke32.
5 Plagman 6
 
484 terminx 7
EDuke32 is free software; you can redistribute it and/or
5 Plagman 8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
331 terminx 13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 Plagman 14
 
15
See the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
4541 hendricks2 19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
5 Plagman 20
*/
21
//-------------------------------------------------------------------------
22
 
23
#include "compat.h"
24
#include "build.h"
25
#include "editor.h"
26
#include "pragmas.h"
3116 hendricks2 27
 
5 Plagman 28
#include "baselayer.h"
3221 hendricks2 29
#include "renderlayer.h"
3116 hendricks2 30
 
5 Plagman 31
#include "osd.h"
32
#include "cache1d.h"
33
 
1952 helixhorne 34
#include "osdfuncs.h"
35
#include "names.h"
36
 
4557 hendricks2 37
#include "grpscan.h"
38
 
2542 helixhorne 39
#include "common.h"
2726 hendricks2 40
#include "common_game.h"
5 Plagman 41
#include "mapster32.h"
42
#include "keys.h"
1346 terminx 43
 
5 Plagman 44
#include "keyboard.h"
249 terminx 45
#include "scriptfile.h"
4387 terminx 46
#include "xxhash.h"
5 Plagman 47
 
1247 helixhorne 48
#include "sounds_mapster32.h"
49
#include "fx_man.h"
50
 
1341 terminx 51
#include "macros.h"
5359 hendricks2 52
#include "colmatch.h"
5789 terminx 53
#include "palette.h"
1341 terminx 54
 
1493 helixhorne 55
#include "m32script.h"
56
#include "m32def.h"
57
 
3056 helixhorne 58
#ifdef LUNATIC
6056 hendricks2 59
# include "lunatic_editor.h"
3056 helixhorne 60
#endif
61
 
1661 helixhorne 62
#include <signal.h>
63
 
4072 hendricks2 64
// Workaround for namespace pollution in <sys/stat.h> introduced in MinGW 4.8.
65
#ifdef stat
66
# undef stat
67
#endif
68
 
4538 hendricks2 69
const char* AppProperName = "Mapster32";
70
const char* AppTechnicalName = "mapster32";
71
 
4558 hendricks2 72
#if defined(_WIN32)
73
#define DEFAULT_GAME_EXEC "eduke32.exe"
74
#define DEFAULT_GAME_LOCAL_EXEC "eduke32.exe"
75
#elif defined(__APPLE__)
76
#define DEFAULT_GAME_EXEC "EDuke32.app/Contents/MacOS/eduke32"
77
#define DEFAULT_GAME_LOCAL_EXEC "EDuke32.app/Contents/MacOS/eduke32"
78
#else
79
#define DEFAULT_GAME_EXEC "eduke32"
80
#define DEFAULT_GAME_LOCAL_EXEC "./eduke32"
81
#endif
82
 
83
const char* DefaultGameExec = DEFAULT_GAME_EXEC;
84
const char* DefaultGameLocalExec = DEFAULT_GAME_LOCAL_EXEC;
85
 
1205 terminx 86
static int32_t floor_over_floor;
1901 helixhorne 87
static int32_t g_fillCurSector = 0;
5 Plagman 88
 
4558 hendricks2 89
const char* defaultsetupfilename = SETUPFILENAME;
4344 hendricks2 90
char setupfilename[BMAX_PATH] = SETUPFILENAME;
2564 helixhorne 91
 
2110 helixhorne 92
static int32_t fixmaponsave_walls = 0;
1205 terminx 93
static int32_t lastsave = -180*60;
94
static int32_t NoAutoLoad = 0;
1644 helixhorne 95
static int32_t spnoclip=1;
5 Plagman 96
 
5547 terminx 97
static char const *default_tiles_cfg = "tiles.cfg";
1695 helixhorne 98
static int32_t pathsearchmode_oninit;
99
 
3056 helixhorne 100
#ifdef LUNATIC
3148 helixhorne 101
static L_State g_EmState;
3056 helixhorne 102
#endif
103
 
1454 terminx 104
#pragma pack(push,1)
1247 helixhorne 105
sound_t g_sounds[MAXSOUNDS];
1454 terminx 106
#pragma pack(pop)
107
 
1247 helixhorne 108
static int16_t g_definedsndnum[MAXSOUNDS];  // maps parse order index to g_sounds index
109
static int16_t g_sndnum[MAXSOUNDS];  // maps current order index to g_sounds index
110
int32_t g_numsounds = 0;
8484 hendricks2 111
static int32_t bstatus;
1247 helixhorne 112
 
1751 helixhorne 113
static int32_t corruptchecktimer;
4561 hendricks2 114
static int32_t curcorruptthing=-1;
1751 helixhorne 115
 
1803 helixhorne 116
static uint32_t templenrepquot=1;
1733 helixhorne 117
 
5374 hendricks2 118
static int32_t duke3d_m32_globalflags;
119
 
5468 hendricks2 120
// KEEPINSYNC global.h (used values only)
121
enum DUKE3D_GLOBALFLAGS {
5375 hendricks2 122
    DUKE3D_NO_HARDCODED_FOGPALS = 1<<1,
5468 hendricks2 123
    DUKE3D_NO_PALETTE_CHANGES = 1<<2,
5375 hendricks2 124
};
125
 
1644 helixhorne 126
//////////////////// Key stuff ////////////////////
127
 
128
#define eitherALT   (keystatus[KEYSC_LALT] || keystatus[KEYSC_RALT])
129
#define eitherCTRL  (keystatus[KEYSC_LCTRL] || keystatus[KEYSC_RCTRL])
130
#define eitherSHIFT (keystatus[KEYSC_LSHIFT] || keystatus[KEYSC_RSHIFT])
131
 
132
#define PRESSED_KEYSC(Key) (keystatus[KEYSC_##Key] && !(keystatus[KEYSC_##Key]=0))
133
 
134
 
135
//////////////////// Aiming ////////////////////
136
static const char *Typestr[] = { "Wall", "Ceiling", "Floor", "Sprite", "Wall" };
137
static const char *typestr[] = { "wall", "ceiling", "floor", "sprite", "wall" };
138
static const char *Typestr_wss[] = { "Wall", "Sector", "Sector", "Sprite", "Wall" };
1660 terminx 139
/*static const char *typestr_wss[] = { "wall", "sector", "sector", "sprite", "wall" };*/
1361 terminx 140
 
1644 helixhorne 141
/** The following macros multiplex between identically named fields of sector/wall/sprite,
142
 * based on a macro parameter or the currently aimed at object (AIMED_ versions).
143
 * They can be used on either side of an assignment. */
144
 
145
// select wall, only makes a difference with walls that have 'swap bottom of walls' bit set
146
#define SELECT_WALL() (AIMING_AT_WALL ? searchbottomwall : searchwall)
147
 
148
#define SECFLD(i, Field)  (sector[i].Field)
149
#define WALFLD(i, Field)  (wall[i].Field)
150
#define SPRFLD(i, Field)  (sprite[i].Field)
151
 
152
// valid fields: z, stat, picnum, heinum, shade, pal, xpanning, ypanning
153
#define CEILINGFLOOR(iSec, Field) (*(AIMING_AT_CEILING ? &(sector[iSec].ceiling##Field) : &(sector[iSec].floor##Field)))
154
#define AIMED_CEILINGFLOOR(Field) CEILINGFLOOR(searchsector, Field)
155
 
156
#define AIMED_SEL_WALL(Field) WALFLD(SELECT_WALL(), Field)
157
 
158
// selects from wall proper or its mask
159
#define OVR_WALL(iWal, Field) (*(AIMING_AT_WALL ? &WALFLD(iWal, Field) : &(wall[iWal].over##Field)))
160
#define AIMED_SELOVR_WALL(Field) OVR_WALL(SELECT_WALL(), Field)
161
 
162
// the base macro to construct field multiplexing macros: wall and sector cases undetermined
163
#define MUXBASE(Field, SectorCase, WallCase) (*(AIMING_AT_CEILING_OR_FLOOR ? (SectorCase) : \
164
                                               (AIMING_AT_WALL_OR_MASK ? (WallCase) : \
165
                                                &SPRFLD(searchwall, Field))))
166
 
167
#define SFBASE_CF(Field, WallCase) MUXBASE(Field, &AIMED_CEILINGFLOOR(Field), WallCase)
168
 
169
#define SFBASE_(Field, WallCase) MUXBASE(Field, &SECFLD(searchsector,Field), WallCase)
170
 
171
#define AIMED(Field) SFBASE_(Field, &WALFLD(searchwall, Field))
172
#define AIMED_SEL(Field) SFBASE_(Field, &AIMED_SEL_WALL(Field))
173
//#define AIMED_CF(Field) SFBASE_CF(Field, &WALFLD(searchwall,Field))
174
#define AIMED_CF_SEL(Field) SFBASE_CF(Field, &AIMED_SEL_WALL(Field))
175
 
176
// OVR makes sense only with picnum
177
//#define AIMED_OVR_PICNUM  SFBASE_CF(picnum, &OVR_WALL(searchwall, picnum))
178
#define AIMED_SELOVR_PICNUM SFBASE_CF(picnum, &AIMED_SELOVR_WALL(picnum))
179
 
180
static const char *ONOFF_[] = {"OFF","ON"};
181
#define ONOFF(b) (ONOFF_[!!(b)])
182
 
4561 hendricks2 183
static int32_t tsign, mouseax=0, mouseay=0;
1361 terminx 184
static int32_t repeatcountx, repeatcounty;
185
static int32_t infobox=3; // bit0: current window, bit1: mouse pointer, the variable should be renamed
186
 
1508 terminx 187
static char wallshades[MAXWALLS];
188
static char sectorshades[MAXSECTORS][2];
189
static char spriteshades[MAXSPRITES];
190
static char wallpals[MAXWALLS];
191
static char sectorpals[MAXSECTORS][2];
192
static char spritepals[MAXSPRITES];
7594 terminx 193
static uint8_t wallflag[(MAXWALLS+7)>>3];
1695 helixhorne 194
 
1854 helixhorne 195
#ifdef YAX_ENABLE
196
static uint8_t havebunch[YAX_MAXBUNCHES];
197
static int32_t *tempzar[YAX_MAXBUNCHES];
198
 
199
static int32_t yax_invalidop()
200
{
201
    silentmessage("Operation forbidden on extended sector.");
202
    return 0;
203
}
204
 
1900 helixhorne 205
static int32_t yax_invalidslope()
206
{
207
    silentmessage("Firstwalls must coincide for changing slope.");
208
    return 0;
209
}
210
 
211
// 1: ok
212
static int32_t yax_checkslope(int16_t sectnum, int32_t othersectnum)
213
{
214
    int16_t w1 = sector[sectnum].wallptr, w2 = wall[w1].point2;
215
    int16_t nw1 = sector[othersectnum].wallptr, nw2 = wall[nw1].point2;
216
 
217
    if (nw1 < 0)
218
        return 0;  // error
219
 
220
    nw2 = wall[nw1].point2;
221
    if (wall[w1].x != wall[nw1].x || wall[w1].y != wall[nw1].y ||
222
            wall[w2].x != wall[nw2].x || wall[w2].y != wall[nw2].y)
223
        return 0;
224
 
225
    return 1;
226
}
227
 
228
# define YAXSLOPECHK(s,os)  (yax_checkslope(s,os) || yax_invalidslope())
1854 helixhorne 229
# define YAXCHK(p) ((p) || yax_invalidop())
230
#endif
231
 
1695 helixhorne 232
// tile marking in tile selector for custom creation of tile groups
1867 helixhorne 233
static uint8_t tilemarked[(MAXTILES+7)>>3];
1695 helixhorne 234
 
1508 terminx 235
#ifdef POLYMER
236
static int16_t spritelightid[MAXSPRITES];
237
_prlight *spritelightptr[MAXSPRITES];
1760 helixhorne 238
 
1854 helixhorne 239
static int32_t check_prlight_colors(int32_t i)
1760 helixhorne 240
{
1854 helixhorne 241
    return (sprite[i].xvel != spritelightptr[i]->color[0]) ||
242
        (sprite[i].yvel != spritelightptr[i]->color[1]) ||
243
        (sprite[i].zvel != spritelightptr[i]->color[2]);
244
}
245
 
246
static void copy_prlight_colors(_prlight *mylightptr, int32_t i)
247
{
248
    mylightptr->color[0] = sprite[i].xvel;
249
    mylightptr->color[1] = sprite[i].yvel;
250
    mylightptr->color[2] = sprite[i].zvel;
251
}
252
 
253
static void addprlight_common1(_prlight *mylightptr, int32_t i)
254
{
5825 terminx 255
    mylightptr->sector = SECT(i);
1854 helixhorne 256
    Bmemcpy(mylightptr, &sprite[i], sizeof(vec3_t));
5825 terminx 257
    mylightptr->range = SHT(i);
1854 helixhorne 258
    copy_prlight_colors(mylightptr, i);
5825 terminx 259
    mylightptr->angle = SA(i);
260
    mylightptr->horiz = SH(i);
1854 helixhorne 261
    mylightptr->minshade = sprite[i].xoffset;
262
    mylightptr->maxshade = sprite[i].yoffset;
263
 
264
    // overridden for spot lights
265
    mylightptr->radius = mylightptr->faderadius = mylightptr->tilenum = 0;
266
 
5825 terminx 267
    if (CS(i) & 2)
1854 helixhorne 268
    {
5825 terminx 269
        if (CS(i) & 512)
1854 helixhorne 270
            mylightptr->priority = PR_LIGHT_PRIO_LOW;
271
        else
272
            mylightptr->priority = PR_LIGHT_PRIO_HIGH;
273
    }
274
    else
275
        mylightptr->priority = PR_LIGHT_PRIO_MAX;
276
 
5825 terminx 277
    mylightptr->publicflags.negative = !!(CS(i) & 128);
3092 Plagman 278
 
1854 helixhorne 279
    spritelightid[i] = polymer_addlight(mylightptr);
280
    if (spritelightid[i] >= 0)
281
        spritelightptr[i] = &prlights[spritelightid[i]];
282
}
283
 
284
static void DeletePolymerLights(void)
285
{
1760 helixhorne 286
    int32_t i;
287
    for (i=0; i<MAXSPRITES; i++)
288
        if (spritelightptr[i] != NULL)
289
        {
290
            polymer_deletelight(spritelightid[i]);
2169 helixhorne 291
            spritelightid[i] = -1;
1760 helixhorne 292
            spritelightptr[i] = NULL;
293
        }
294
}
2006 helixhorne 295
 
296
void G_Polymer_UnInit(void)
297
{
298
    DeletePolymerLights();
299
}
1508 terminx 300
#endif
301
 
1454 terminx 302
extern int32_t mskip;
1361 terminx 303
 
1843 helixhorne 304
//extern int32_t fillsector(int16_t sectnum, char fillcolor);
1361 terminx 305
 
7154 terminx 306
static int osdcmd_quit(osdcmdptr_t parm);
2492 helixhorne 307
 
1361 terminx 308
 
4385 terminx 309
#define M32_NUM_SPRITE_MODES (signed)ARRAY_SIZE(SpriteMode)
1644 helixhorne 310
static const char *SpriteMode[]=
559 terminx 311
{
312
    "NONE",
313
    "SECTORS",
314
    "WALLS",
315
    "SPRITES",
316
    "ALL",
317
    "ITEMS ONLY",
318
    "CURRENT SPRITE ONLY",
319
    "ONLY SECTOREFFECTORS AND SECTORS",
320
    "NO SECTOREFFECTORS OR SECTORS"
321
};
5 Plagman 322
 
323
#define MAXSKILL 5
1644 helixhorne 324
static const char *SKILLMODE[MAXSKILL]=
559 terminx 325
{
326
    "Actor skill display: PIECE OF CAKE",
327
    "Actor skill display: LET'S ROCK",
328
    "Actor skill display: COME GET SOME",
329
    "Actor skill display: DAMN I'M GOOD",
330
    "Actor skill display: ALL SKILL LEVELS"
331
};
5 Plagman 332
 
333
#define MAXNOSPRITES 4
1644 helixhorne 334
static const char *SPRDSPMODE[MAXNOSPRITES]=
559 terminx 335
{
336
    "Sprite display: DISPLAY ALL SPRITES",
337
    "Sprite display: NO EFFECTORS",
338
    "Sprite display: NO ACTORS",
339
    "Sprite display: NO EFFECTORS OR ACTORS"
340
};
5 Plagman 341
 
4385 terminx 342
#define MAXHELP3D (signed)ARRAY_SIZE(Help3d)
1644 helixhorne 343
static const char *Help3d[]=
559 terminx 344
{
345
    "Mapster32 3D mode help",
346
    " ",
347
    " F2 = TOGGLE CLIPBOARD",
1856 helixhorne 348
    " F3 = TOGGLE MOUSELOOK",
349
    " F4 = TOGGLE AMBIENT SOUNDS",
559 terminx 350
    " F6 = AUTOMATIC SECTOREFFECTOR HELP",
351
    " F7 = AUTOMATIC SECTOR TAG HELP",
352
    "",
353
    " ' A = TOGGLE AUTOSAVE",
354
    " ' D = CYCLE SPRITE SKILL DISPLAY",
355
    " ' R = TOGGLE FRAMERATE DISPLAY",
356
    " ' W = TOGGLE SPRITE DISPLAY",
763 terminx 357
    " ' X = MAP SHADE PREVIEW",
1856 helixhorne 358
    " ' I = TOGGLE INVISIBLE SPRITES",
559 terminx 359
    "",
360
    " ' T = CHANGE LOTAG",
361
    " ' H = CHANGE HITAG",
362
    " ' S = CHANGE SHADE",
363
    " ' M = CHANGE EXTRA",
364
    " ' V = CHANGE VISIBILITY",
365
    " ' L = CHANGE OBJECT COORDINATES",
366
    " ' C = CHANGE GLOBAL SHADE",
367
    "",
368
    " ' ENTER = PASTE GRAPHIC ONLY",
369
    " ' P & ; P = PASTE PALETTE TO ALL SELECTED SECTORS",
370
    " ; V = SET VISIBILITY ON ALL SELECTED SECTORS",
371
    " ' DEL = CSTAT=0",
372
    " CTRL-S = SAVE BOARD",
373
    " HOME = PGUP/PGDN MODIFIER (256 UNITS)",
374
    " END = PGUP/PGDN MODIFIER (512 UNITS)",
375
};
5 Plagman 376
 
1824 terminx 377
const char *ExtGetVer(void)
378
{
379
    return s_buildRev;
380
}
381
 
2110 helixhorne 382
void ExtSetupMapFilename(const char *mapname)
383
{
4558 hendricks2 384
    UNREFERENCED_PARAMETER(mapname);
2110 helixhorne 385
}
386
 
5 Plagman 387
void ExtLoadMap(const char *mapname)
388
{
4558 hendricks2 389
    UNREFERENCED_PARAMETER(mapname);
390
 
783 terminx 391
    getmessageleng = 0;
392
    getmessagetimeoff = 0;
393
 
3976 helixhorne 394
    // Old-fashioned multi-psky handling setup.
395
    G_SetupGlobalPsky();
1882 helixhorne 396
 
3975 helixhorne 397
    parallaxtype = 0;
5 Plagman 398
 
1882 helixhorne 399
    //////////
1973 helixhorne 400
#if M32_UNDO
1384 terminx 401
    map_undoredo_free();
1973 helixhorne 402
#endif
5 Plagman 403
}
404
 
405
void ExtSaveMap(const char *mapname)
406
{
654 terminx 407
    UNREFERENCED_PARAMETER(mapname);
5 Plagman 408
}
409
 
1866 helixhorne 410
 
411
////////// tag labeling system //////////
412
 
1867 helixhorne 413
#define TLCHAR "+"
414
#define TLCHR(Cond) ((Cond)?TLCHAR:"")
3108 helixhorne 415
static uint64_t taglab_nolink_SEs = (1ull<<10)|(1ull<<27)|(1ull<<28)|(1ull<<29)|
416
    (1ull<<31)|(1ull<<32)|(1ull<<49)|(1ull<<50);
1866 helixhorne 417
 
4465 helixhorne 418
//// Case lists of switch picnums. Pretty much CODEDUP from sector.c.
419
 
420
// List of switches that function like dip (combination lock) switches.
421
#define DIPSWITCH_LIKE_CASES \
422
         DIPSWITCH: \
423
    case TECHSWITCH: \
424
    case ALIENSWITCH
425
 
426
// List of access switches.
427
#define ACCESS_SWITCH_CASES \
428
         ACCESSSWITCH: \
429
    case ACCESSSWITCH2
430
 
431
// List of switches that don't fit the two preceding categories, and are not
432
// the MULTISWITCH. 13 cases.
433
#define REST_SWITCH_CASES \
434
         DIPSWITCH2: \
435
    case DIPSWITCH3: \
436
    case FRANKENSTINESWITCH: \
437
    case HANDSWITCH: \
438
    case LIGHTSWITCH2: \
439
    case LIGHTSWITCH: \
440
    case LOCKSWITCH1: \
441
    case POWERSWITCH1: \
442
    case POWERSWITCH2: \
443
    case PULLSWITCH: \
444
    case SLOTDOOR: \
445
    case SPACEDOORSWITCH: \
446
    case SPACELIGHTSWITCH
447
 
1866 helixhorne 448
// Whether the individual tags have linking semantics. Based on
449
//  http://infosuite.duke4.net/index.php?page=references_special_textures
450
// The return value is an OR of the following:
451
//  1: lotag has linking semantics
452
//  2: hitag
453
//  4: extra
454
//  8: xvel
455
//  16: yvel
456
//  32: zvel
457
//  64: owner
1877 helixhorne 458
// This function is only supposed to say something about the potential of a tag:
459
// it will also 'say yes' if a particular tag is zero.
1866 helixhorne 460
int32_t taglab_linktags(int32_t spritep, int32_t num)
461
{
462
    int32_t picnum;
463
    int32_t l, link = 0;
464
 
465
    if (spritep)
466
        picnum = sprite[num].picnum;
467
    else
468
        picnum = wall[num].picnum;
469
 
470
    if (spritep)
471
    {
472
        switch (picnum)
473
        {
474
        case SECTOREFFECTOR:
475
            // SEs potentially link by their hitag
476
            l = sprite[num].lotag;
477
            if (l>=0 && l<=63 && (taglab_nolink_SEs&(1ull<<l)))
478
                break;
3424 helixhorne 479
            link = 2;
1866 helixhorne 480
            break;
481
 
482
            // various lotag-linkers
4465 helixhorne 483
            // NOTE: switch picnums are handled together with walls below.
1866 helixhorne 484
        case ACTIVATOR: case TOUCHPLATE: case ACTIVATORLOCKED: case MASTERSWITCH:
485
        case RESPAWN:  // ---
486
        case MULTISWITCH:  // *
4465 helixhorne 487
        case TARGET: case DUCK:
1866 helixhorne 488
        case REACTOR:
489
        case CAMERA1:
3424 helixhorne 490
            link = 1;
1866 helixhorne 491
            break;
492
 
493
            // various hitag-linkers
494
        case VIEWSCREEN2: case VIEWSCREEN:
495
        case CRACK1: case CRACK2: case CRACK3: case CRACK4: case FIREEXT:
496
        case FEM1: case FEM2: case FEM3: case FEM4: case FEM5: case FEM6:
497
        case FEM7: case FEM8: case FEM9: case FEM10: case PODFEM1: case NAKED1: //case STATUE: //?
498
        case SEENINE: case OOZFILTER:
499
        case CRANEPOLE: case CRANE:
500
        case NATURALLIGHTNING:
3424 helixhorne 501
            link = 2;
1866 helixhorne 502
            break;
503
        }
504
    }
505
    else  // walls
506
    {
2496 helixhorne 507
#ifdef YAX_ENABLE
4465 helixhorne 508
        // XXX: only for non-VX map versions.
2496 helixhorne 509
        if (yax_getnextwall(num, YAX_CEILING) < 0)
510
#endif
1866 helixhorne 511
        switch (picnum)
512
        {
513
        case TECHLIGHT2: case TECHLIGHT4: case WALLLIGHT4:
514
        case WALLLIGHT3: case WALLLIGHT1: case WALLLIGHT2:
515
        case BIGFORCE: case W_FORCEFIELD:
3424 helixhorne 516
            link = 1;
1866 helixhorne 517
            break;
518
        }
519
    }
520
 
521
    if (!link)
2496 helixhorne 522
#ifdef YAX_ENABLE
523
    if (spritep || yax_getnextwall(num, YAX_CEILING) < 0)
524
#endif
1866 helixhorne 525
    {
526
        // try a few that work both as sprites and as walls
527
        switch (picnum)
528
        {
4465 helixhorne 529
        case ACCESS_SWITCH_CASES:
530
        case DIPSWITCH_LIKE_CASES:
531
        case REST_SWITCH_CASES:
1866 helixhorne 532
        case DOORTILE5: case DOORTILE6: case DOORTILE1: case DOORTILE2: case DOORTILE3:
533
        case DOORTILE4: case DOORTILE7: case DOORTILE8: case DOORTILE9: case DOORTILE10:
534
        case DOORTILE22: case DOORTILE18: case DOORTILE19: case DOORTILE20:
535
        case DOORTILE14: case DOORTILE16: case DOORTILE15: case DOORTILE21:
536
        case DOORTILE17: case DOORTILE11: case DOORTILE12: case DOORTILE23:  // ---
3424 helixhorne 537
            link = 1;
1866 helixhorne 538
            break;
539
        }
4465 helixhorne 540
 
541
        // handle 'on' positions of non-access switches
542
        switch (picnum - 1)
543
        {
544
        case DIPSWITCH_LIKE_CASES:
545
        case REST_SWITCH_CASES:
546
            link = 1;
547
            break;
548
        }
549
 
550
        // handle all positions of the multiswitch
551
        if (picnum >= MULTISWITCH && picnum <= MULTISWITCH+3)
552
            link = 1;
1866 helixhorne 553
    }
1867 helixhorne 554
 
555
    g_iReturnVar = link;
556
    VM_OnEvent(EVENT_LINKTAGS, spritep?num:-1);
557
    link = g_iReturnVar;
558
 
1866 helixhorne 559
    return link;
560
}
561
 
4464 helixhorne 562
// <duetoptr>: if non-NULL, a value will be written denoting the object with
563
// the currently greatest tag:
564
//  32768 + spritenum, or
565
//  wallnum, or
566
//  -1 (the return value i.e. no more tags left OR there are no tagged objects)
567
int32_t taglab_getnextfreetag(int32_t *duetoptr)
1867 helixhorne 568
{
3108 helixhorne 569
    int32_t i, nextfreetag=1;
4464 helixhorne 570
    int32_t obj = -1;
3108 helixhorne 571
 
1867 helixhorne 572
    for (i=0; i<MAXSPRITES; i++)
573
    {
3108 helixhorne 574
        int32_t tag;
575
 
1867 helixhorne 576
        if (sprite[i].statnum == MAXSTATUS)
577
            continue;
578
 
579
        if (sprite[i].picnum==MULTISWITCH)
580
        {
581
            // MULTISWITCH needs special care
582
            int32_t endtag = sprite[i].lotag+3;
4464 helixhorne 583
 
1867 helixhorne 584
            if (nextfreetag <= endtag)
4464 helixhorne 585
            {
1867 helixhorne 586
                nextfreetag = endtag+1;
4464 helixhorne 587
                obj = 32768 + i;
588
            }
589
 
1867 helixhorne 590
            continue;
591
        }
592
 
3108 helixhorne 593
        tag = select_sprite_tag(i);
594
 
595
        if (tag != INT32_MIN && nextfreetag <= tag)
4464 helixhorne 596
        {
3108 helixhorne 597
            nextfreetag = tag+1;
4464 helixhorne 598
            obj = 32768 + i;
599
        }
1867 helixhorne 600
    }
601
 
602
    for (i=0; i<numwalls; i++)
603
    {
3108 helixhorne 604
        int32_t lt = taglab_linktags(0, i);
605
 
1867 helixhorne 606
        if ((lt&1) && nextfreetag <= wall[i].lotag)
4464 helixhorne 607
            nextfreetag = wall[i].lotag+1, obj = i;
1867 helixhorne 608
        if ((lt&2) && nextfreetag <= wall[i].hitag)
4464 helixhorne 609
            nextfreetag = wall[i].hitag+1, obj = i;
1867 helixhorne 610
    }
611
 
4464 helixhorne 612
    if (duetoptr != NULL)
613
        *duetoptr = obj;
614
 
1867 helixhorne 615
    if (nextfreetag < 32768)
616
        return nextfreetag;
617
 
618
    return 0;
619
}
620
 
621
 
622
static void taglab_handle1(int32_t linktagp, int32_t tagnum, char *buf)
623
{
5290 terminx 624
    char const * const label = (linktagp && showtags==2) ? taglab_getlabel(tagnum) : NULL;
1867 helixhorne 625
 
626
    if (label)
2158 helixhorne 627
        Bsprintf(buf, "%d<%s>", tagnum, label);
1867 helixhorne 628
    else
2158 helixhorne 629
        Bsprintf(buf, "%d%s", tagnum, TLCHR(linktagp));
1867 helixhorne 630
}
1866 helixhorne 631
////////// end tag labeling system //////////
632
 
633
 
1644 helixhorne 634
static int32_t getTileGroup(const char *groupName)
858 terminx 635
{
1205 terminx 636
    int32_t temp;
858 terminx 637
    for (temp = 0; temp < MAX_TILE_GROUPS; temp++)
638
    {
859 terminx 639
        if (s_TileGroups[temp].szText == NULL)
858 terminx 640
            return -1;
1644 helixhorne 641
 
642
        if (!Bstrcmp(s_TileGroups[temp].szText, groupName))
858 terminx 643
            return temp;
644
    }
645
    return -1;
646
}
647
 
1644 helixhorne 648
static int32_t tileInGroup(int32_t group, int32_t tilenum)
858 terminx 649
{
650
    // @todo Make a bitmap instead of doing this slow search..
1205 terminx 651
    int32_t temp;
858 terminx 652
    if (group < 0 || group >= MAX_TILE_GROUPS || s_TileGroups[group].szText == NULL)
653
    {
654
        // group isn't valid.
655
        return 0;
656
    }
1644 helixhorne 657
    for (temp=0; temp<s_TileGroups[group].nIds; temp++)
858 terminx 658
    {
659
        if (tilenum == s_TileGroups[group].pIds[temp])
660
            return 1;
661
    }
662
    return 0;
663
}
664
 
1205 terminx 665
const char *ExtGetSectorType(int32_t lotag)
1049 terminx 666
{
667
    switch (lotag)
668
    {
5289 terminx 669
    case 1: return "WATER";
670
    case 2: return "UNDERWATER";
1865 helixhorne 671
    case 9: return "STAR TREK DOORS";
672
    case 15: return "ELEVATOR TRANSPORT (SE 17)";
673
    case 16: return "ELEVATOR PLATFORM DOWN";
674
    case 17: return "ELEVATOR PLATFORM UP";
675
    case 18: return "ELEVATOR DOWN";
676
    case 19: return "ELEVATOR UP";
677
    case 20: return "CEILING DOOR";
678
    case 21: return "FLOOR DOOR";
679
    case 22: return "SPLIT DOOR";
680
    case 23: return "SWING DOOR (SE 11)";
681
    case 25: return "SLIDE DOOR (SE 15)";
682
    case 26: return "SPLIT STAR TREK DOOR";
683
    case 27: return "BRIDGE (SE 20)";
684
    case 28: return "DROP FLOOR (SE 21)";
685
    case 29: return "TEETH DOOR (SE 22)";
686
    case 30: return "ROTATE RISE BRIDGE";
687
    case 31: return "2 WAY TRAIN (SE=30)";
5289 terminx 688
    case 32767: return "SECRET AREA";
1865 helixhorne 689
    case -1: return "END OF LEVEL";
690
    default:
1049 terminx 691
        if (lotag > 10000 && lotag < 32767)
1865 helixhorne 692
            return "1 TIME SOUND";
693
//        else Bsprintf(tempbuf,"%hu",lotag);
1049 terminx 694
    }
1865 helixhorne 695
 
696
    return "";
1049 terminx 697
}
698
 
1205 terminx 699
const char *ExtGetSectorCaption(int16_t sectnum)
5 Plagman 700
{
1049 terminx 701
    static char tempbuf[64];
5 Plagman 702
 
1644 helixhorne 703
    Bmemset(tempbuf, 0, sizeof(tempbuf));
704
 
3823 helixhorne 705
    if (!in3dmode() && ((onnames!=1 && onnames!=4 && onnames!=7) || onnames==8))
1644 helixhorne 706
        return tempbuf;
707
 
3823 helixhorne 708
    if (in3dmode() || (sector[sectnum].lotag|sector[sectnum].hitag))
5 Plagman 709
    {
1644 helixhorne 710
        Bstrcpy(lo, ExtGetSectorType(sector[sectnum].lotag));
3823 helixhorne 711
        if (!in3dmode())
6951 hendricks2 712
            Bsnprintf(tempbuf, sizeof(tempbuf), "%hu,%hu %s", TrackerCast(sector[sectnum].hitag), TrackerCast(sector[sectnum].lotag), lo);
1644 helixhorne 713
        else
6951 hendricks2 714
            Bsnprintf(tempbuf, sizeof(tempbuf), "%hu %s", TrackerCast(sector[sectnum].lotag), lo);
5 Plagman 715
    }
5803 terminx 716
    return tempbuf;
5 Plagman 717
}
718
 
1205 terminx 719
const char *ExtGetWallCaption(int16_t wallnum)
5 Plagman 720
{
1049 terminx 721
    static char tempbuf[64];
1047 terminx 722
 
1044 terminx 723
    Bmemset(tempbuf,0,sizeof(tempbuf));
7870 terminx 724
 
7876 terminx 725
    if (editwall[wallnum>>3]&pow2char[wallnum&7])
1047 terminx 726
    {
1644 helixhorne 727
        Bsprintf(tempbuf,"%d", wallength(wallnum));
7876 terminx 728
        editwall[wallnum>>3] &= ~pow2char[wallnum&7];
5803 terminx 729
        return tempbuf;
1047 terminx 730
    }
731
 
331 terminx 732
    if (!(onnames==2 || onnames==4))
5 Plagman 733
    {
734
        tempbuf[0] = 0;
5803 terminx 735
        return tempbuf;
5 Plagman 736
    }
737
 
738
    // HERE
739
 
740
    if ((wall[wallnum].lotag|wall[wallnum].hitag) == 0)
741
        tempbuf[0] = 0;
742
    else
1865 helixhorne 743
    {
1866 helixhorne 744
        int32_t lt = taglab_linktags(0, wallnum);
1867 helixhorne 745
        char histr[TAGLAB_MAX+16], lostr[TAGLAB_MAX+16];
746
 
3178 helixhorne 747
        lt &= ~(int)(wall[wallnum].lotag<=0);
748
        lt &= ~(int)((wall[wallnum].hitag<=0)<<1);
1867 helixhorne 749
 
750
        taglab_handle1(lt&2, wall[wallnum].hitag, histr);
751
 
3658 helixhorne 752
#ifdef YAX_ENABLE__COMPAT
1865 helixhorne 753
        if (yax_getnextwall(wallnum, YAX_CEILING) >= 0)  // ceiling nextwall: lotag
754
        {
755
            if (wall[wallnum].hitag == 0)
756
                tempbuf[0] = 0;
757
            else
1867 helixhorne 758
                Bsprintf(tempbuf, "%s,*", histr);
1865 helixhorne 759
        }
760
        else
761
#endif
1867 helixhorne 762
        {
763
            taglab_handle1(lt&1, wall[wallnum].lotag, lostr);
6951 hendricks2 764
            Bsnprintf(tempbuf, sizeof(tempbuf), "%s,%s", histr, lostr);
1867 helixhorne 765
        }
1865 helixhorne 766
    }
1644 helixhorne 767
 
5803 terminx 768
    return tempbuf;
5 Plagman 769
} //end
770
 
1205 terminx 771
const char *SectorEffectorTagText(int32_t lotag)
5 Plagman 772
{
1049 terminx 773
    static char tempbuf[64];
1644 helixhorne 774
 
1677 terminx 775
    static const char *tags[] =
776
    {
1644 helixhorne 777
        "ROTATED SECTOR",                // 0
5289 terminx 778
        "ROTATION PIVOT",
1644 helixhorne 779
        "EARTHQUAKE",
780
        "RANDOM LIGHTS AFTER SHOT OUT",
781
        "RANDOM LIGHTS",
782
        "(UNKNOWN)",                     // 5
783
        "SUBWAY",
784
        "TRANSPORT",
5289 terminx 785
        "RISING DOOR LIGHTS",
786
        "LOWERING DOOR LIGHTS",
787
        "DOOR CLOSE DELAY",              // 10
788
        "SWING DOOR PIVOT (ST 23)",
1644 helixhorne 789
        "LIGHT SWITCH",
790
        "EXPLOSIVE",
791
        "SUBWAY CAR",
792
        "SLIDE DOOR (ST 25)",            // 15
793
        "ROTATE REACTOR SECTOR",
794
        "ELEVATOR TRANSPORT (ST 15)",
795
        "INCREMENTAL SECTOR RISE/FALL",
796
        "CEILING FALL ON EXPLOSION",
797
        "BRIDGE (ST 27)",                // 20
798
        "DROP FLOOR (ST 28)",
799
        "TEETH DOOR (ST 29)",
5289 terminx 800
        "1-WAY TRANSPORT DESTINATION",
801
        "CONVEYOR BELT",
1644 helixhorne 802
        "ENGINE",                        // 25
803
        "(UNKNOWN)",
5289 terminx 804
        "DEMO CAMERA",
805
        "LIGHTNING (4890) CONTROLLER",
1644 helixhorne 806
        "FLOAT",
5289 terminx 807
        "2 WAY TRAIN (ST 31)",           // 30
808
        "FLOOR Z",
809
        "CEILING Z",
810
        "EARTHQUAKE DEBRIS",
1644 helixhorne 811
    };
812
 
1044 terminx 813
    Bmemset(tempbuf,0,sizeof(tempbuf));
1644 helixhorne 814
 
4385 terminx 815
    if (lotag>=0 && lotag<(int32_t)ARRAY_SIZE(tags))
5289 terminx 816
        Bsprintf(tempbuf, "%s", tags[lotag]);
1644 helixhorne 817
    else
818
        switch (lotag)
819
        {
820
        case 36:
5289 terminx 821
            Bsprintf(tempbuf,"SHOOTER");
1644 helixhorne 822
            break;
823
        case 49:
5289 terminx 824
            Bsprintf(tempbuf,"POINT LIGHT");
1644 helixhorne 825
            break;
826
        case 50:
5289 terminx 827
            Bsprintf(tempbuf,"SPOTLIGHT");
1644 helixhorne 828
            break;
829
        default:
830
            Bsprintf(tempbuf,"%d: (UNKNOWN)",lotag);
831
            break;
832
        }
833
 
5803 terminx 834
    return tempbuf;
5 Plagman 835
}
836
 
1253 helixhorne 837
const char *MusicAndSFXTagText(int32_t lotag)
838
{
839
    static char tempbuf[16];
840
 
841
    Bmemset(tempbuf, 0, sizeof(tempbuf));
842
 
843
    if (g_numsounds <= 0)
1316 terminx 844
        return tempbuf;
1253 helixhorne 845
 
846
    if (lotag>0 && lotag<999 && g_sounds[lotag].definedname)
847
        return g_sounds[lotag].definedname;
848
 
849
    if (lotag>=1000 && lotag<2000)
850
        Bsprintf(tempbuf, "REVERB");
851
    return tempbuf;
852
}
853
 
1205 terminx 854
const char *SectorEffectorText(int32_t spritenum)
1049 terminx 855
{
856
    static char tempbuf[64];
1644 helixhorne 857
 
858
    Bmemset(tempbuf, 0, sizeof(tempbuf));
859
    Bmemset(lo, 0, sizeof(lo));
860
 
861
    Bstrcpy(lo, SectorEffectorTagText(sprite[spritenum].lotag));
1049 terminx 862
    if (!lo[5]) // tags are 5 chars or less
1644 helixhorne 863
        SpriteName(spritenum, tempbuf);
864
    else
5289 terminx 865
    {
866
        if (cursprite == spritenum)
6951 hendricks2 867
            Bsnprintf(tempbuf, sizeof(tempbuf), "SE %d %s", TrackerCast(sprite[spritenum].lotag), lo);
5289 terminx 868
        else Bstrcpy(tempbuf, lo);
869
    }
1644 helixhorne 870
 
5803 terminx 871
    return tempbuf;
1049 terminx 872
}
873
 
1205 terminx 874
const char *ExtGetSpriteCaption(int16_t spritenum)
5 Plagman 875
{
1041 terminx 876
    static char tempbuf[1024];
1866 helixhorne 877
    int32_t retfast = 0, lt;
1044 terminx 878
 
1644 helixhorne 879
    if (!(onnames>=3 && onnames<=8) || (onnames==7 && sprite[spritenum].picnum!=SECTOREFFECTOR))
880
        retfast = 1;
881
    if (onnames==5 && !tileInGroup(tilegroupItems, sprite[spritenum].picnum))
882
        retfast = 1;
883
    if (onnames==6 && sprite[spritenum].picnum != sprite[cursprite].picnum)
884
        retfast = 1;
5 Plagman 885
 
5670 terminx 886
    tempbuf[0] = 0;
887
 
1644 helixhorne 888
    if (retfast)
1867 helixhorne 889
        return tempbuf;
5 Plagman 890
 
1866 helixhorne 891
    lt = taglab_linktags(1, spritenum);
3178 helixhorne 892
    lt &= ~(int)(sprite[spritenum].lotag<=0);
893
    lt &= ~(int)((sprite[spritenum].hitag<=0)<<1);
1866 helixhorne 894
 
5 Plagman 895
    if ((sprite[spritenum].lotag|sprite[spritenum].hitag) == 0)
896
    {
5670 terminx 897
        Bmemset(tempbuf, 0, sizeof(tempbuf));
5 Plagman 898
        SpriteName(spritenum,lo);
5670 terminx 899
 
331 terminx 900
        if (lo[0]!=0)
5 Plagman 901
        {
5290 terminx 902
            Bsprintf(tempbuf,"%s",lo);
903
 
1866 helixhorne 904
            if (sprite[spritenum].pal==1)
5290 terminx 905
                Bstrcat(tempbuf," (MULTIPLAYER)");
5 Plagman 906
        }
1867 helixhorne 907
 
908
        return tempbuf;
5 Plagman 909
    }
1867 helixhorne 910
 
5290 terminx 911
    char histr[TAGLAB_MAX+16], lostr[TAGLAB_MAX+16];
1867 helixhorne 912
 
5290 terminx 913
    taglab_handle1(lt&2, sprite[spritenum].hitag, histr);
1867 helixhorne 914
 
5290 terminx 915
    if (sprite[spritenum].picnum==SECTOREFFECTOR)
916
    {
917
        if (onnames!=8)
5 Plagman 918
        {
5670 terminx 919
            Bmemset(tempbuf, 0, sizeof(tempbuf));
5290 terminx 920
            Bsprintf(lo,"%s",SectorEffectorText(spritenum));
921
            Bsprintf(tempbuf,"%s, %s",lo, histr);
5 Plagman 922
        }
5290 terminx 923
    }
924
    else
925
    {
5670 terminx 926
        Bmemset(tempbuf, 0, sizeof(tempbuf));
5290 terminx 927
        taglab_handle1(lt&1, sprite[spritenum].lotag, lostr);
928
        SpriteName(spritenum,lo);
929
 
930
        if (sprite[spritenum].extra != -1)
931
            Bsprintf(tempbuf,"%s,%s,%d %s", histr, lostr, TrackerCast(sprite[spritenum].extra), lo);
5 Plagman 932
        else
5290 terminx 933
            Bsprintf(tempbuf,"%s,%s %s", histr, lostr, lo);
1229 terminx 934
    }
1644 helixhorne 935
 
1867 helixhorne 936
    return tempbuf;
5 Plagman 937
 
938
} //end
939
 
940
//printext16 parameters:
1205 terminx 941
//printext16(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol,
5 Plagman 942
//           char name[82], char fontsize)
943
//  xpos 0-639   (top left)
944
//  ypos 0-479   (top left)
945
//  col 0-15
946
//  backcol 0-15, -1 is transparent background
947
//  name
948
//  fontsize 0=8*8, 1=3*5
949
 
950
//drawline16 parameters:
1205 terminx 951
// drawline16(int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col)
5 Plagman 952
//  x1, x2  0-639
953
//  y1, y2  0-143  (status bar is 144 high, origin is top-left of STATUS BAR)
954
//  col     0-15
955
 
1797 helixhorne 956
static void PrintStatus(const char *string, int32_t num, int32_t x, int32_t y, int32_t color)
957
{
958
    Bsprintf(tempbuf, "%s %d", string, num);
959
    printext16(x*8, ydim-STATUS2DSIZ+y*8, editorcolors[color], -1, tempbuf, 0);
960
}
961
 
4464 helixhorne 962
static void PrintNextTag(void)
963
{
964
    int32_t obj;
965
    int32_t nexttag = taglab_getnextfreetag(&obj);
966
 
967
    if (nexttag >= 1)
968
    {
969
        if (obj == -1)
970
            printmessage16("Level %s next tag %d (no tagged objects)", levelname, nexttag);
971
        else
972
            printmessage16("Level %s next tag %d (%s %d has greatest)", levelname, nexttag,
973
                           (obj&32768) ? "sprite" : "wall", obj&32767);
974
    }
975
}
976
 
1205 terminx 977
void ExtShowSectorData(int16_t sectnum)   //F5
5 Plagman 978
{
1205 terminx 979
    int32_t x,x2,y;
1644 helixhorne 980
    int32_t i,yi;
1205 terminx 981
    int32_t secrets=0;
982
    int32_t totalactors1=0,totalactors2=0,totalactors3=0,totalactors4=0;
983
    int32_t totalrespawn=0;
5 Plagman 984
 
654 terminx 985
    UNREFERENCED_PARAMETER(sectnum);
3823 helixhorne 986
    if (in3dmode())
5 Plagman 987
        return;
988
 
1229 terminx 989
    for (i=0; i<numsectors; i++)
1644 helixhorne 990
        secrets += (sector[i].lotag==32767);
5 Plagman 991
 
1865 helixhorne 992
    for (i=headspritestat[0]; i != -1; i=nextspritestat[i])
5 Plagman 993
    {
858 terminx 994
        // Count all non-player actors.
995
        if (tileInGroup(tilegroupActors, sprite[i].picnum))
5 Plagman 996
        {
808 terminx 997
            if (sprite[i].lotag<=1) totalactors1++;
998
            if (sprite[i].lotag<=2) totalactors2++;
999
            if (sprite[i].lotag<=3) totalactors3++;
1000
            if (sprite[i].lotag<=4) totalactors4++;
858 terminx 1001
        }
5 Plagman 1002
 
1797 helixhorne 1003
        if (sprite[i].picnum == RESPAWN)
1004
            totalrespawn++;
5 Plagman 1005
    }
1006
 
1644 helixhorne 1007
    Bmemset(numsprite, 0, sizeof(numsprite));
1008
    Bmemset(multisprite, 0, sizeof(numsprite));
1009
 
1229 terminx 1010
    for (i=0; i<MAXSPRITES; i++)
5 Plagman 1011
    {
1797 helixhorne 1012
        if (sprite[i].statnum==0 && sprite[i].picnum>=0 && sprite[i].picnum<MAXTILES)
5 Plagman 1013
        {
1644 helixhorne 1014
            if (sprite[i].pal!=0)
1015
                multisprite[sprite[i].picnum]++;
1016
            else
1017
                numsprite[sprite[i].picnum]++;
5 Plagman 1018
        }
1019
    }
1020
 
1021
    clearmidstatbar16();             //Clear middle of status bar
1392 helixhorne 1022
 
1023
    ydim -= 8;
1644 helixhorne 1024
    drawgradient();
1392 helixhorne 1025
    ydim += 8;
1026
 
4464 helixhorne 1027
    PrintNextTag();
5 Plagman 1028
 
1644 helixhorne 1029
#define PRSTAT(Str, Tiledef) \
1648 helixhorne 1030
    PrintStatus(Str, numsprite[Tiledef], x, y+yi, numsprite[Tiledef]?11:7); \
1031
    PrintStatus("",multisprite[Tiledef], x2,y+yi, multisprite[Tiledef]?9:7); \
1644 helixhorne 1032
    yi++;
1033
 
1034
    ydim -= 8; // vvvvvv reset at end!!
1035
 
6828 terminx 1036
    videoBeginDrawing();  //{{{
1797 helixhorne 1037
 
1644 helixhorne 1038
    x=1; x2=14;
1039
    y=4; yi=2;
1040
    printext16(x*8, ydim-STATUS2DSIZ+y*8, editorcolors[11], -1, "Item Count", 0);
5 Plagman 1041
 
1644 helixhorne 1042
    PRSTAT("10%health=", COLA);
1043
    PRSTAT("30%health=", SIXPAK);
1044
    PRSTAT("Med-Kit  =", FIRSTAID);
1045
    PRSTAT("Atom     =", ATOMICHEALTH);
1046
    PRSTAT("Shields  =", SHIELD);
1047
 
1048
    x=17; x2=30;
1049
    y=4; yi=2;
1050
    printext16(x*8, ydim-STATUS2DSIZ+y*8, editorcolors[11], -1, "Inventory", 0);
5 Plagman 1051
 
1644 helixhorne 1052
    PRSTAT("Steroids =", STEROIDS);
1053
    PRSTAT("Airtank  =", AIRTANK);
1054
    PRSTAT("Jetpack  =", JETPACK);
1055
    PRSTAT("Goggles  =", HEATSENSOR);
1056
    PRSTAT("Boots    =", BOOTS);
1057
    PRSTAT("HoloDuke =", HOLODUKE);
1058
    PRSTAT("Multi D  =", APLAYER);
1059
 
1060
    x=33; x2=46;
1061
    y=4; yi=2;
1062
    printext16(x*8, ydim-STATUS2DSIZ+y*8, editorcolors[11], -1, "Weapon Count", 0);
5 Plagman 1063
 
1644 helixhorne 1064
    PRSTAT("Pistol   =", FIRSTGUNSPRITE);
1065
    PRSTAT("Shotgun  =", SHOTGUNSPRITE);
1066
    PRSTAT("Chaingun =", CHAINGUNSPRITE);
1067
    PRSTAT("RPG      =", RPGSPRITE);
1068
    PRSTAT("Pipe Bomb=", HEAVYHBOMB);
1069
    PRSTAT("Shrinker =", SHRINKERSPRITE);
1070
    PRSTAT("Devastatr=", DEVISTATORSPRITE);
1071
    PRSTAT("Trip mine=", TRIPBOMBSPRITE);
1072
    PRSTAT("Freezeray=", FREEZESPRITE);
1073
 
1074
    x=49; x2=62;
1075
    y=4; yi=2;
1361 terminx 1076
    printext16(x*8,ydim-STATUS2DSIZ+y*8,editorcolors[11],-1,"Ammo Count",0);
5 Plagman 1077
 
1644 helixhorne 1078
    PRSTAT("Pistol   =", AMMO);
1079
    PRSTAT("Shot     =", SHOTGUNAMMO);
1080
    PRSTAT("Chain    =", BATTERYAMMO);
1081
    PRSTAT("RPG Box  =", RPGAMMO);
1082
    PRSTAT("Pipe Bomb=", HBOMBAMMO);
1083
    PRSTAT("Shrinker =", CRYSTALAMMO);
1084
    PRSTAT("Devastatr=", DEVISTATORAMMO);
1085
    PRSTAT("Expander =", GROWAMMO);
1086
    PRSTAT("Freezeray=", FREEZEAMMO);
1087
 
1088
    printext16(65*8, ydim-STATUS2DSIZ+4*8, editorcolors[11], -1, "MISC", 0);
1089
    printext16(65*8, ydim-STATUS2DSIZ+8*8, editorcolors[11], -1, "ACTORS", 0);
5 Plagman 1090
 
1644 helixhorne 1091
#undef PRSTAT
1092
 
1093
    PrintStatus("Secrets =", secrets, 65, 6, 11);
1094
    PrintStatus("Skill 1 =", totalactors1, 65, 10, 11);
1095
    PrintStatus("Skill 2 =", totalactors2, 65, 11, 11);
1096
    PrintStatus("Skill 3 =", totalactors3, 65, 12, 11);
1097
    PrintStatus("Skill 4 =", totalactors4, 65, 13, 11);
1098
    PrintStatus("Respawn =", totalrespawn, 65, 14, 11);
1099
 
6828 terminx 1100
    videoEndDrawing();  //}}}
1797 helixhorne 1101
 
1644 helixhorne 1102
    ydim += 8; // ^^^^^^ see above!
1867 helixhorne 1103
}
1644 helixhorne 1104
 
1205 terminx 1105
void ExtShowWallData(int16_t wallnum)       //F6
5 Plagman 1106
{
1867 helixhorne 1107
    int32_t i, runi, total=0, x, y, yi;
5 Plagman 1108
 
654 terminx 1109
    UNREFERENCED_PARAMETER(wallnum);
649 terminx 1110
 
3823 helixhorne 1111
    if (in3dmode())
5 Plagman 1112
        return;
1113
 
1644 helixhorne 1114
    clearmidstatbar16();
1115
    drawgradient();
1116
 
4464 helixhorne 1117
    PrintNextTag();
1644 helixhorne 1118
 
1119
#define CASES_LIZTROOP \
1120
    LIZTROOP: case LIZTROOPRUNNING : case LIZTROOPSTAYPUT: case LIZTROOPSHOOT: \
1121
              case LIZTROOPJETPACK: case LIZTROOPONTOILET: case LIZTROOPDUCKING
1122
#define CASES_BOSS1  BOSS1: case BOSS1STAYPUT: case BOSS1SHOOT: case BOSS1LOB: case BOSSTOP
1123
 
1124
    Bmemset(numsprite, 0, sizeof(numsprite));
1125
    Bmemset(multisprite, 0, sizeof(multisprite));
1126
 
1229 terminx 1127
    for (i=0; i<MAXSPRITES; i++)
5 Plagman 1128
    {
1644 helixhorne 1129
        if (sprite[i].statnum==0 && sprite[i].pal)
1130
            switch (sprite[i].picnum)
1131
            {
1132
            case CASES_LIZTROOP:
1133
                numsprite[LIZTROOP]++;
1134
                break;
1135
            case CASES_BOSS1:
1136
                multisprite[BOSS1]++;
1137
                break;
1138
            case BOSS2:
1139
                multisprite[BOSS2]++;
1140
                break;
1141
            case BOSS3:
1142
                multisprite[BOSS3]++;
1143
            default:
1144
                break;
1145
            }
1146
    }
1147
 
1797 helixhorne 1148
    // runi==0: Count Normal Actors
1149
    // runi==1: Count Respawn Actors
1644 helixhorne 1150
    for (runi=0; runi<2; runi++)
1151
    {
1797 helixhorne 1152
        if (runi==1)
5 Plagman 1153
        {
1644 helixhorne 1154
            Bmemset(numsprite, 0, sizeof(numsprite));
1155
            Bmemset(multisprite, 0, sizeof(multisprite));
1156
        }
5 Plagman 1157
 
1644 helixhorne 1158
        for (i=0; i<MAXSPRITES; i++)
1159
        {
1797 helixhorne 1160
            int32_t pic;
1161
 
1162
            if (sprite[i].statnum!=0)
1163
                continue;
1164
 
1165
            if (runi==0 && sprite[i].pal!=0)
1166
                continue;
1167
 
1168
            if (runi==1 && sprite[i].picnum!=RESPAWN)
1169
                continue;
1170
 
3178 helixhorne 1171
            pic = (runi==0) ? (int)sprite[i].picnum : (int)sprite[i].hitag;
1797 helixhorne 1172
            if (pic<0 || pic>=MAXTILES)
1173
                continue;
1174
 
1175
            switch (pic)
1644 helixhorne 1176
            {
1797 helixhorne 1177
            case CASES_LIZTROOP:
1178
                numsprite[LIZTROOP]++;
1179
                break;
1180
            case PIGCOP: case PIGCOPSTAYPUT: case PIGCOPDIVE:
1181
                numsprite[PIGCOP]++;
1182
                break;
1183
            case LIZMAN: case LIZMANSTAYPUT: case LIZMANSPITTING: case LIZMANFEEDING: case LIZMANJUMP:
1184
                numsprite[LIZMAN]++;
1185
                break;
1186
            case CASES_BOSS1:
1187
                if (runi==0 || sprite[i].pal==0)
1188
                    numsprite[BOSS1]++;
1189
                else
1190
                    multisprite[BOSS1]++;
1191
                break;
1192
            case COMMANDER:
1193
            case COMMANDERSTAYPUT:
1194
                numsprite[COMMANDER]++;
1195
                break;
1196
            case OCTABRAIN:
1197
            case OCTABRAINSTAYPUT:
1198
                numsprite[OCTABRAIN]++;
1199
                break;
1200
            case RECON: case DRONE: case ROTATEGUN: case EGG: case ORGANTIC: case GREENSLIME:
1201
            case BOSS2: case BOSS3: case TANK: case NEWBEAST: case NEWBEASTSTAYPUT: case BOSS4:
1202
                numsprite[pic]++;
1203
                break;
1204
            default:
1205
                break;
1206
            }
1207
        }
337 terminx 1208
 
1644 helixhorne 1209
#undef CASES_LIZTROOP
1210
#undef CASES_BOSS1
337 terminx 1211
 
1644 helixhorne 1212
        total=0;
1797 helixhorne 1213
        for (i=0; i<MAXTILES; i++)
1644 helixhorne 1214
            total += numsprite[i];
1797 helixhorne 1215
        for (i=0; i<MAXTILES; i++)
1644 helixhorne 1216
            total += multisprite[i];
1392 helixhorne 1217
 
6828 terminx 1218
        videoBeginDrawing();  //{{{
1797 helixhorne 1219
 
1644 helixhorne 1220
        x=2+runi*34;
1221
        y=4;
1648 helixhorne 1222
        PrintStatus(runi==0?"Normal actors:":"Respawn actors:", total, x, y, 11);
337 terminx 1223
 
1648 helixhorne 1224
#define PRSTAT(Str, Tiledef)  PrintStatus(Str, numsprite[Tiledef], x, y+(yi++), numsprite[Tiledef]?11:7);
1644 helixhorne 1225
        yi=1;
337 terminx 1226
 
1644 helixhorne 1227
        PRSTAT(" Liztroop  =", LIZTROOP);
1228
        PRSTAT(" Lizman    =", LIZMAN);
1229
        PRSTAT(" Commander =", COMMANDER);
1230
        PRSTAT(" Octabrain =", OCTABRAIN);
1231
        PRSTAT(" PigCop    =", PIGCOP);
1232
        PRSTAT(" Recon Car =", RECON);
1233
        PRSTAT(" Drone     =", DRONE);
1234
        PRSTAT(" Turret    =", ROTATEGUN);
1235
        PRSTAT(" Egg       =", EGG);
337 terminx 1236
 
1644 helixhorne 1237
        x+=17;
1238
        yi=1;
1239
        PRSTAT("Slimer    =", GREENSLIME);
1240
        PRSTAT("Boss1     =", BOSS1);
1648 helixhorne 1241
        PrintStatus("MiniBoss1 =", multisprite[BOSS1], x, y+(yi++), multisprite[BOSS1]?11:7);
1644 helixhorne 1242
        PRSTAT("Boss2     =", BOSS2);
1243
        PRSTAT("Boss3     =", BOSS3);
1244
        PRSTAT("Riot Tank =", TANK);
1245
        PRSTAT("Newbeast  =", NEWBEAST);
1246
        PRSTAT("Boss4     =", BOSS4);
1247
#undef PRSTAT
1797 helixhorne 1248
 
6828 terminx 1249
        videoEndDrawing();  //}}}
1644 helixhorne 1250
    }
1867 helixhorne 1251
}
5 Plagman 1252
 
1797 helixhorne 1253
// formerly Show2dText and Show3dText
1959 helixhorne 1254
static void ShowFileText(const char *name)
5 Plagman 1255
{
3823 helixhorne 1256
    int32_t fp,t;
1205 terminx 1257
    uint8_t x=0,y=4,xmax=0,xx=0,col=0;
1644 helixhorne 1258
 
3823 helixhorne 1259
    if (!in3dmode())
1797 helixhorne 1260
    {
1261
        clearmidstatbar16();
1262
        drawgradient();
1263
    }
1392 helixhorne 1264
 
331 terminx 1265
    if ((fp=kopen4load(name,0)) == -1)
5 Plagman 1266
    {
2538 hendricks2 1267
        Bsprintf(tempbuf, "ERROR: file \"%s\" not found.", name);
3823 helixhorne 1268
        if (in3dmode())
1797 helixhorne 1269
            printext256(1*4,4*8,whitecol,-1,tempbuf,0);
1270
        else
1271
            printext16(1*4,ydim-STATUS2DSIZ+4*8,editorcolors[11],-1,tempbuf,0);
5 Plagman 1272
        return;
1273
    }
1274
 
1275
    t=65;
6828 terminx 1276
    videoBeginDrawing();
331 terminx 1277
    while (t!=EOF && col<5)
5 Plagman 1278
    {
1279
        t = 0;
1280
        if (kread(fp,&t,1)<=0)
1281
            t = EOF;
331 terminx 1282
        while (t!=EOF && t!='\n' && x<250)
5 Plagman 1283
        {
1284
            tempbuf[x]=t;
335 terminx 1285
            t = 0;
1286
            if (kread(fp,&t,1)<=0) t = EOF;
1287
            x++;
1288
            if (x>xmax) xmax=x;
5 Plagman 1289
        }
1290
        tempbuf[x]=0;
1797 helixhorne 1291
 
3823 helixhorne 1292
        if (in3dmode())
1797 helixhorne 1293
            printext256(xx*4,(y*6)+2,whitecol,-1,tempbuf,1);
1294
        else
1295
            printext16(xx*4,ydim-STATUS2DSIZ+(y*6)+2,editorcolors[11],-1,tempbuf,1);
1296
 
335 terminx 1297
        x=0;
1298
        y++;
1299
        if (y>18)
1300
        {
1301
            col++;
1302
            y=6;
1303
            xx+=xmax;
1304
            xmax=0;
5 Plagman 1305
        }
1306
    }
6828 terminx 1307
    videoEndDrawing();
5 Plagman 1308
 
1309
    kclose(fp);
1310
 
1867 helixhorne 1311
}
5 Plagman 1312
 
764 terminx 1313
// PK_ vvvv
1314
typedef struct helppage_
1315
{
1205 terminx 1316
    int32_t numlines;
4995 terminx 1317
    char line[1][80];  // C99 flexible array member
764 terminx 1318
} helppage_t;
1319
 
1644 helixhorne 1320
static helppage_t **helppage=NULL;
1321
static int32_t numhelppages=0;
764 terminx 1322
 
1205 terminx 1323
static int32_t emptyline(const char *start)
1048 terminx 1324
{
1205 terminx 1325
    int32_t i;
1048 terminx 1326
    for (i=0; i<80; i++)
1327
    {
1328
        if (start[i]=='\n' || !start[i]) break;
1329
        if (start[i]!=' ' && start[i]!='\t' && start[i]!='\r')
1330
            return 0;
1331
    }
1332
    return 1;
1333
}
1334
 
1205 terminx 1335
static int32_t newpage(const char *start)
764 terminx 1336
{
1205 terminx 1337
    int32_t i;
976 terminx 1338
    for (i=80-1; i>=0; i--)
764 terminx 1339
    {
784 terminx 1340
        if (start[i] == '^' && start[i+1] == 'P')
1341
            return 1;
764 terminx 1342
    }
784 terminx 1343
    return 0;
764 terminx 1344
}
1345
 
1346
#define IHELP_INITPAGES 32
1347
#define IHELP_INITLINES 16
1348
 
1349
static void ReadHelpFile(const char *name)
1350
{
1351
    BFILE *fp;
1205 terminx 1352
    int32_t i, j, k, numallocpages;
1353
    int32_t pos, charsread=0;
764 terminx 1354
    helppage_t *hp;
1355
    char skip=0;
1356
 
1040 terminx 1357
    initprintf("Loading \"%s\"\n",name);
1358
 
764 terminx 1359
    if ((fp=fopenfrompath(name,"rb")) == NULL)
1360
    {
1361
        initprintf("Error initializing integrated help: file \"%s\" not found.\n", name);
1362
        return;
1363
    }
1364
 
4491 helixhorne 1365
    helppage=(helppage_t **)Xmalloc(IHELP_INITPAGES * sizeof(helppage_t *));
764 terminx 1366
    numallocpages=IHELP_INITPAGES;
1367
 
1368
    i=0;
1369
    while (!Bfeof(fp) && !ferror(fp))
1370
    {
1371
        while (!Bfeof(fp))    // skip empty lines
1372
        {
1373
            pos = ftell(fp);
1103 terminx 1374
            if (Bfgets(tempbuf, 80, fp) == NULL) break;
764 terminx 1375
            charsread = ftell(fp)-pos;
784 terminx 1376
            if (!newpage(tempbuf))
764 terminx 1377
            {
1378
                break;
1379
            }
1380
        }
1381
 
1382
        if (Bfeof(fp) || charsread<=0) break;
1383
 
4491 helixhorne 1384
        hp=(helppage_t *)Xcalloc(1,sizeof(helppage_t) + IHELP_INITLINES*80);
1385
 
764 terminx 1386
        hp->numlines = IHELP_INITLINES;
1387
 
1388
        if (charsread == 79 && tempbuf[78]!='\n') skip=1;
1389
        j=0;
1390
 
1391
        do
1392
        {
1393
            if (j >= hp->numlines)
1394
            {
4491 helixhorne 1395
                hp=(helppage_t *)Xrealloc(hp, sizeof(helppage_t) + 2*hp->numlines*80);
764 terminx 1396
                hp->numlines *= 2;
1397
            }
1398
 
1399
            // limit the line length to 78 chars and probably get rid of the CR
1400
            if (charsread>0)
1401
            {
1402
                tempbuf[charsread-1]=0;
2161 helixhorne 1403
                if (charsread>=2 && tempbuf[charsread-2]==0x0d)
1404
                    tempbuf[charsread-2]=0;
764 terminx 1405
            }
1406
 
1425 terminx 1407
            Bmemcpy(hp->line[j], tempbuf, 80);
764 terminx 1408
 
1409
            for (k=charsread; k<80; k++) hp->line[j][k]=0;
1410
 
1411
            if (skip)
1412
            {
1413
                while (fgetc(fp)!='\n' && !Bfeof(fp)) /*skip rest of line*/;
1414
                skip=0;
1415
            }
1416
 
1417
            pos = ftell(fp);
1103 terminx 1418
            if (Bfgets(tempbuf, 80, fp) == NULL) break;
764 terminx 1419
            charsread = ftell(fp)-pos;
1420
            if (charsread == 79 && tempbuf[78]!='\n') skip=1;
1421
 
1422
            j++;
1423
 
1424
        }
784 terminx 1425
        while (!newpage(tempbuf) && !Bfeof(fp) && charsread>0);
764 terminx 1426
 
4491 helixhorne 1427
        hp=(helppage_t *)Xrealloc(hp, sizeof(helppage_t) + j*80);
764 terminx 1428
        hp->numlines=j;
1429
 
1430
        if (i >= numallocpages)
1431
        {
4491 helixhorne 1432
            helppage = (helppage_t **)Xrealloc(helppage, 2*numallocpages*sizeof(helppage_t *));
764 terminx 1433
            numallocpages *= 2;
1434
        }
1435
        helppage[i] = hp;
1436
        i++;
1437
    }
1438
 
4491 helixhorne 1439
    helppage =(helppage_t **)Xrealloc(helppage, i*sizeof(helppage_t *));
764 terminx 1440
    numhelppages = i;
1441
 
1442
    Bfclose(fp);
1443
}
1444
 
1050 terminx 1445
// why can't MSVC allocate an array of variable size?!
1396 helixhorne 1446
#define IHELP_NUMDISPLINES 110 // ((overridepm16y>>4)+(overridepm16y>>5)+(overridepm16y>>7)-2)
764 terminx 1447
#define IHELP_PATLEN 45
1648 helixhorne 1448
extern int32_t overridepm16y;  // influences clearmidstatbar16()
764 terminx 1449
 
1854 helixhorne 1450
static void IntegratedHelp(void)
764 terminx 1451
{
1452
    if (!helppage) return;
1453
 
1361 terminx 1454
    overridepm16y = ydim;//3*STATUS2DSIZ;
1048 terminx 1455
 
1049 terminx 1456
    {
1644 helixhorne 1457
        int32_t i, j;
1205 terminx 1458
        static int32_t curhp=0, curline=0;
1459
        int32_t highlighthp=-1, highlightline=-1, lasthighlighttime=0;
1049 terminx 1460
        char disptext[IHELP_NUMDISPLINES][80];
1461
        char oldpattern[IHELP_PATLEN+1];
1048 terminx 1462
 
1648 helixhorne 1463
        Bmemset(oldpattern, 0, sizeof(char));
1444 terminx 1464
        //    clearmidstatbar16();
764 terminx 1465
 
6828 terminx 1466
        videoBeginDrawing();
1854 helixhorne 1467
        CLEARLINES2D(0, ydim, 0);
6828 terminx 1468
        videoEndDrawing();
1854 helixhorne 1469
 
1049 terminx 1470
        while (keystatus[KEYSC_ESC]==0 && keystatus[KEYSC_Q]==0 && keystatus[KEYSC_F1]==0)
764 terminx 1471
        {
1486 helixhorne 1472
            idle_waitevent();
1049 terminx 1473
            if (handleevents())
1644 helixhorne 1474
                quitevent = 0;
1475
 
1444 terminx 1476
            //        printmessage16("Help mode, press <Esc> to exit");
764 terminx 1477
 
1854 helixhorne 1478
            if (keystatus[KEYSC_S])
1048 terminx 1479
            {
1869 helixhorne 1480
                fade_editor_screen(-1);
1854 helixhorne 1481
            }
1482
            else
1483
            {
6828 terminx 1484
                videoBeginDrawing();
1854 helixhorne 1485
                CLEARLINES2D(0, ydim, 0);
6828 terminx 1486
                videoEndDrawing();
1854 helixhorne 1487
            }
1488
 
1489
            // based on 'save as' dialog in overheadeditor()
1490
            if (keystatus[KEYSC_S])    // text search
1491
            {
1492
                char ch, bad=0, pattern[IHELP_PATLEN+1];
1493
 
1494
                for (i=0; i<IHELP_PATLEN+1; i++) pattern[i]=0;
1495
 
1496
                i=0;
6827 terminx 1497
                keyFlushChars();
1854 helixhorne 1498
                while (bad == 0)
1499
                {
1500
                    _printmessage16("Search: %s_", pattern);
6828 terminx 1501
                    videoShowFrame(1);
1854 helixhorne 1502
 
1503
                    idle_waitevent();
1504
 
1505
                    if (handleevents())
1506
                        quitevent = 0;
1507
 
6827 terminx 1508
                    ch = keyGetChar();
1854 helixhorne 1509
 
6860 terminx 1510
                    if (keystatus[sc_Escape]) bad = 1;
1854 helixhorne 1511
                    else if (ch == 13) bad = 2;
1512
                    else if (ch > 0)
1513
                    {
1514
                        if (i > 0 && (ch == 8 || ch == 127))
1515
                        {
1516
                            i--;
1517
                            pattern[i] = 0;
1518
                        }
1519
                        else if (i < IHELP_PATLEN && ch >= 32 && ch < 128)
1520
                        {
1521
                            pattern[i++] = ch;
1522
                            pattern[i] = 0;
1523
                        }
1524
                    }
1525
                }
1526
 
1527
                if (bad==1)
1528
                {
1529
                    keystatus[KEYSC_ESC] = keystatus[KEYSC_Q] = keystatus[KEYSC_F1] = 0;
1530
                }
1531
 
1532
                if (bad==2)
1533
                {
1534
                    keystatus[KEYSC_ENTER] = 0;
1535
 
1536
                    for (i=curhp; i<numhelppages; i++)
1537
                    {
1538
                        for (j = (i==curhp)?(curline+1):0; j<helppage[i]->numlines; j++)
1539
                        {
1540
                            // entering an empty pattern will search with the last used pattern
1874 helixhorne 1541
                            if (Bstrstr(helppage[i]->line[j], pattern[0]?pattern:oldpattern))
1854 helixhorne 1542
                            {
1543
                                curhp = i;
1544
 
1545
                                if ((curline=j) <= helppage[i]->numlines - 32 /*-IHELP_NUMDISPLINES*/) /**/;
1546
                                else if ((curline=helppage[i]->numlines- 32 /*-IHELP_NUMDISPLINES*/) >= 0) /**/;
1547
                                else curline=0;
1548
 
1549
                                highlighthp = i;
1550
                                highlightline = j;
8050 pogokeen 1551
                                lasthighlighttime = (int32_t) totalclock;
1854 helixhorne 1552
                                goto ENDFOR1;
1553
                            }
1554
                        }
1555
                    }
1556
ENDFOR1:
1557
                    if (pattern[0])
1558
                        Bmemcpy(oldpattern, pattern, IHELP_PATLEN+1);
1559
                }
1560
            }
1561
            else if (PRESSED_KEYSC(T))    // goto table of contents
1562
            {
1049 terminx 1563
                curhp=0;
1564
                curline=0;
1048 terminx 1565
            }
1644 helixhorne 1566
            else if (PRESSED_KEYSC(G))    // goto arbitrary page
1048 terminx 1567
            {
1644 helixhorne 1568
                curhp=getnumber16("Goto page: ", 0, numhelppages-1, 0);
1049 terminx 1569
                curline=0;
1048 terminx 1570
            }
1644 helixhorne 1571
            else if (PRESSED_KEYSC(UP))    // scroll up
1048 terminx 1572
            {
1049 terminx 1573
                if (curline>0) curline--;
1048 terminx 1574
            }
1644 helixhorne 1575
            else if (PRESSED_KEYSC(DOWN))    // scroll down
764 terminx 1576
            {
1361 terminx 1577
                if (curline + 32/*+IHELP_NUMDISPLINES*/ < helppage[curhp]->numlines) curline++;
764 terminx 1578
            }
1644 helixhorne 1579
            else if (PRESSED_KEYSC(PGUP))    // scroll one page up
764 terminx 1580
            {
1049 terminx 1581
                i=IHELP_NUMDISPLINES;
1582
                while (i>0 && curline>0) i--, curline--;
1583
            }
1644 helixhorne 1584
            else if (PRESSED_KEYSC(PGDN))    // scroll one page down
1049 terminx 1585
            {
1586
                i=IHELP_NUMDISPLINES;
1361 terminx 1587
                while (i>0 && curline + 32/*+IHELP_NUMDISPLINES*/ < helppage[curhp]->numlines) i--, curline++;
1049 terminx 1588
            }
1644 helixhorne 1589
            else if (PRESSED_KEYSC(SPACE))   // goto next paragraph
1049 terminx 1590
            {
1591
                for (i=curline, j=0; i < helppage[curhp]->numlines; i++)
1592
                {
1593
                    if (emptyline(helppage[curhp]->line[i])) { j=1; continue; }
1594
                    if (j==1 && !emptyline(helppage[curhp]->line[i])) { j=2; break; }
1595
                }
1596
                if (j==2)
1597
                {
1361 terminx 1598
                    if (i + 32 /*+IHELP_NUMDISPLINES*/ < helppage[curhp]->numlines)
1049 terminx 1599
                        curline=i;
1361 terminx 1600
                    else if (helppage[curhp]->numlines - 32/*-IHELP_NUMDISPLINES*/ > curline)
1601
                        curline = helppage[curhp]->numlines - 32/*-IHELP_NUMDISPLINES*/;
1049 terminx 1602
                }
1603
            }
1644 helixhorne 1604
            else if (PRESSED_KEYSC(BS))   // goto prev paragraph
1049 terminx 1605
            {
1606
                for (i=curline-1, j=0; i>=0; i--)
1607
                {
1608
                    if (!emptyline(helppage[curhp]->line[i])) { j=1; continue; }
1609
                    if (j==1 && emptyline(helppage[curhp]->line[i])) { j=2; break; }
1610
                }
1611
                if (j==2 || i==-1) curline=i+1;
1612
            }
1644 helixhorne 1613
            else if (PRESSED_KEYSC(HOME))    // goto beginning of page
1049 terminx 1614
            {
764 terminx 1615
                curline=0;
1616
            }
1644 helixhorne 1617
            else if (PRESSED_KEYSC(END))    // goto end of page
1049 terminx 1618
            {
1361 terminx 1619
                if ((curline=helppage[curhp]->numlines - 32/*-IHELP_NUMDISPLINES*/) >= 0) /**/;
1049 terminx 1620
                else curline=0;
1621
            }
1644 helixhorne 1622
            else if (PRESSED_KEYSC(LEFT) || PRESSED_KEYSC(LBRACK))    // prev page
1049 terminx 1623
            {
1624
                if (curhp>0)
1625
                {
1626
                    curhp--;
1627
                    curline=0;
1628
                }
1629
            }
1644 helixhorne 1630
            else if (PRESSED_KEYSC(RIGHT) || PRESSED_KEYSC(RBRACK))    // next page
1049 terminx 1631
            {
1632
                if (curhp<numhelppages-1)
1633
                {
1634
                    curhp++;
1635
                    curline=0;
1636
                }
1637
            }
1638
            else    // '1'-'0' on the upper row
764 terminx 1639
            {
1049 terminx 1640
                for (i=2; i<=11; i++)
1641
                    if (keystatus[i]) break;
1642
                if (i--<12 && i<numhelppages)
1643
                {
1644
                    curhp=i;
1645
                    curline=0;
1646
                }
764 terminx 1647
            }
1648
 
1648 helixhorne 1649
//            drawgradient();
1055 terminx 1650
 
6828 terminx 1651
            videoBeginDrawing();
1644 helixhorne 1652
            printext16(9, ydim2d-overridepm16y+9, editorcolors[4], -1, "Help Mode", 0);
1653
            printext16(8, ydim2d-overridepm16y+8, editorcolors[12], -1, "Help Mode", 0);
1648 helixhorne 1654
            printext16(8 + 9*8 + 2*8, ydim2d-overridepm16y+8, editorcolors[15], -1, "(S:search)", 0);
6828 terminx 1655
            videoEndDrawing();
1055 terminx 1656
 
1049 terminx 1657
            if (curhp < helppage[0]->numlines)
1644 helixhorne 1658
                _printmessage16("%s", helppage[0]->line[curhp]);
1049 terminx 1659
            else
1644 helixhorne 1660
                _printmessage16("%d. (Untitled page)", curhp);
764 terminx 1661
 
1049 terminx 1662
            for (i=0; j=(curhp==0)?(i+curline+1):(i+curline),
1450 terminx 1663
                    i<IHELP_NUMDISPLINES && j<helppage[curhp]->numlines; i++)
1049 terminx 1664
            {
1648 helixhorne 1665
                if (ydim-overridepm16y+28+i*9+32 >= ydim)
1666
                    break;
1049 terminx 1667
                Bmemcpy(disptext[i], helppage[curhp]->line[j], 80);
1648 helixhorne 1668
                printext16(8, ydim-overridepm16y+28+i*9, editorcolors[10],
1450 terminx 1669
                           (j==highlightline && curhp==highlighthp
1677 terminx 1670
                            && totalclock-lasthighlighttime<120*5) ?
1648 helixhorne 1671
                           editorcolors[1] : -1,
1672
                           disptext[i], 0);
1049 terminx 1673
            }
1674
 
6828 terminx 1675
            videoShowFrame(1);
764 terminx 1676
        }
1677
 
2488 helixhorne 1678
        clearkeys();
1679
    }
1049 terminx 1680
 
2488 helixhorne 1681
    overridepm16y = -1;
764 terminx 1682
}
1247 helixhorne 1683
 
1684
#define SOUND_NUMDISPLINES IHELP_NUMDISPLINES
1685
 
1250 helixhorne 1686
static int32_t compare_sounds_s(int16_t k1, int16_t k2)
1249 helixhorne 1687
{
1688
    return (int32_t)k1 - (int32_t)k2;
1689
}
1250 helixhorne 1690
static int32_t compare_sounds_d(int16_t k1, int16_t k2)
1249 helixhorne 1691
{
1692
    sound_t *s1 = &g_sounds[k1], *s2 = &g_sounds[k2];
1693
    char *n1 = s1->definedname, *n2 = s2->definedname;
1694
 
1695
    if (!n1 && !n2) return 0;
1696
    if (!n1) return -1;
1697
    if (!n2) return 1;
1316 terminx 1698
    return Bstrcasecmp(n1, n2);
1249 helixhorne 1699
}
1250 helixhorne 1700
static int32_t compare_sounds_f(int16_t k1, int16_t k2)
1249 helixhorne 1701
{
1702
    sound_t *s1 = &g_sounds[k1], *s2 = &g_sounds[k2];
1703
    char *n1 = s1->filename, *n2 = s2->filename;
1704
 
1705
    if (!n1 && !n2) return 0;
1706
    if (!n1) return -1;
1707
    if (!n2) return 1;
1316 terminx 1708
    return Bstrcasecmp(n1, n2);
1249 helixhorne 1709
}
1250 helixhorne 1710
static int32_t compare_sounds_1(int16_t k1, int16_t k2)
1249 helixhorne 1711
{
1712
    return (g_sounds[k2].m&1) - (g_sounds[k1].m&1);
1713
}
1250 helixhorne 1714
static int32_t compare_sounds_2(int16_t k1, int16_t k2)
1249 helixhorne 1715
{
1316 terminx 1716
    return (g_sounds[k2].m&2) - (g_sounds[k1].m&2);
1249 helixhorne 1717
}
1250 helixhorne 1718
static int32_t compare_sounds_3(int16_t k1, int16_t k2)
1249 helixhorne 1719
{
1720
    return (g_sounds[k2].m&4) - (g_sounds[k1].m&4);
1721
}
1250 helixhorne 1722
static int32_t compare_sounds_4(int16_t k1, int16_t k2)
1249 helixhorne 1723
{
1724
    return (g_sounds[k2].m&8) - (g_sounds[k1].m&8);
1725
}
1250 helixhorne 1726
static int32_t compare_sounds_5(int16_t k1, int16_t k2)
1249 helixhorne 1727
{
1728
    return (g_sounds[k2].m&16) - (g_sounds[k1].m&16);
1729
}
1730
 
1731
 
1732
static int32_t sort_sounds(int32_t how)
1733
{
1734
    int32_t (*compare_sounds)(int16_t, int16_t) = NULL;
1735
 
1736
    int32_t ms, ofs, l, lb, r, rb, d, n, k1, k2;
1737
    int16_t *src, *dst, *source, *dest, *tmp;
1738
 
1739
    n = g_numsounds;
1740
    src = source = g_sndnum;
4491 helixhorne 1741
    dest = (int16_t *)Xmalloc(sizeof(int16_t) * n);
1249 helixhorne 1742
    dst = dest;
1743
 
1744
    switch (how)
1745
    {
1746
    case 'g':  // restore original order
1747
        Bmemcpy(g_sndnum, g_definedsndnum, sizeof(int16_t)*n);
7705 terminx 1748
        Xfree(dst);
1249 helixhorne 1749
        return 0;
1750
    case 's':
1250 helixhorne 1751
        compare_sounds = compare_sounds_s;
1249 helixhorne 1752
        break;
1753
    case 'd':
1754
        compare_sounds = compare_sounds_d;
1755
        break;
1756
    case 'f':
1757
        compare_sounds = compare_sounds_f;
1758
        break;
1759
    case '1':
1760
        compare_sounds = compare_sounds_1;
1761
        break;
1762
    case '2':
1763
        compare_sounds = compare_sounds_2;
1764
        break;
1765
    case '3':
1766
        compare_sounds = compare_sounds_3;
1767
        break;
1768
    case '4':
1769
        compare_sounds = compare_sounds_4;
1770
        break;
1771
    case '5':
1772
        compare_sounds = compare_sounds_5;
1773
        break;
1774
    default:
7705 terminx 1775
        Xfree(dst);
1249 helixhorne 1776
        return -2;
1777
    }
1778
 
1779
    for (ms=1; ms<n; ms*=2)
1780
    {
1781
        for (ofs=0; ofs<n; ofs+=2*ms)
1782
        {
1783
            l = ofs;
1784
            r = ofs+ms;
1785
            d = ofs;
1786
            lb = min((l+ms), n);
1787
            rb = min((r+ms), n);
1788
            while (l < lb || r < rb)
1789
            {
1790
                if (l >= lb)
1791
                {
1792
                    dst[d++] = src[r++];
1793
                    continue;
1794
                }
1795
                if (r >= rb)
1796
                {
1797
                    dst[d++] = src[l++];
1798
                    continue;
1799
                }
1800
                k1 = src[l];
1801
                k2 = src[r];
1802
                if (compare_sounds(k1, k2) <= 0)
1803
                {
1804
                    dst[d++] = src[l++];
1805
                    continue;
1316 terminx 1806
                }
1249 helixhorne 1807
                dst[d++] = src[r++];
1808
            }
1809
        }
1810
        tmp = src;
1811
        src = dst;
1812
        dst = tmp;
1813
    }
1814
    if (src != source)
1815
        Bmemcpy(source, src, sizeof(int16_t) * n);
1816
 
7705 terminx 1817
    Xfree(dest);
1249 helixhorne 1818
    return 0;
1819
}
1820
 
1854 helixhorne 1821
static void SoundDisplay(void)
1247 helixhorne 1822
{
1823
    if (g_numsounds <= 0) return;
1824
 
1361 terminx 1825
    overridepm16y = ydim;//3*STATUS2DSIZ;
1247 helixhorne 1826
 
1827
    {
1828
        // cursnd is the first displayed line, cursnd+curofs is where the cursor is
1829
        static int32_t cursnd=0, curofs=0;
2488 helixhorne 1830
        char disptext[80];
1247 helixhorne 1831
 
2488 helixhorne 1832
        int32_t i, j;
1833
        const int32_t halfpage = (ydim-64)/(2*9);
1834
 
1251 helixhorne 1835
        while (keystatus[KEYSC_ESC]==0 && keystatus[KEYSC_Q]==0 && keystatus[KEYSC_F2]==0
1677 terminx 1836
                && keystatus[buildkeys[BK_MODE2D_3D]]==0)  // quickjump to 3d mode
1247 helixhorne 1837
        {
6828 terminx 1838
            videoBeginDrawing();
1648 helixhorne 1839
            CLEARLINES2D(0, ydim16, 0);
6828 terminx 1840
            videoEndDrawing();
1648 helixhorne 1841
 
1486 helixhorne 1842
            idle_waitevent();
1247 helixhorne 1843
            if (handleevents())
1644 helixhorne 1844
                quitevent = 0;
1247 helixhorne 1845
 
1648 helixhorne 1846
//            drawgradient();
1361 terminx 1847
 
6828 terminx 1848
            videoBeginDrawing();
1644 helixhorne 1849
            printext16(9, ydim2d-overridepm16y+9, editorcolors[4], -1, "Sound Index", 0);
1850
            printext16(8, ydim2d-overridepm16y+8, editorcolors[12], -1, "Sound Index", 0);
1648 helixhorne 1851
            printext16(8 + 11*8 + 2*8, ydim2d-overridepm16y+8, editorcolors[15], -1, "(SPACE:play, S:sort)", 0);
6828 terminx 1852
            videoEndDrawing();
1361 terminx 1853
 
1644 helixhorne 1854
            if (PRESSED_KEYSC(G))    // goto specified sound#
1247 helixhorne 1855
            {
1361 terminx 1856
                _printmessage16("                                                    ");
7547 terminx 1857
                j = getnumber16("Goto sound#: ", 0, MAXSOUNDS-1, 0);
1247 helixhorne 1858
                for (i=0; i<g_numsounds; i++)
1859
                    if (g_sndnum[i]==j)
1860
                        break;
1861
                if (i != g_numsounds)
1862
                {
1863
                    if (i<SOUND_NUMDISPLINES)
1864
                        cursnd = 0, curofs = i;
2488 helixhorne 1865
                    else if (i>=g_numsounds-halfpage)
1866
                        cursnd = g_numsounds-halfpage, curofs = i-cursnd;
1247 helixhorne 1867
                    else
2488 helixhorne 1868
                        curofs = halfpage/2, cursnd = i-curofs;
1247 helixhorne 1869
                }
1870
            }
1644 helixhorne 1871
            else if (PRESSED_KEYSC(UP))    // scroll up
1247 helixhorne 1872
            {
1873
                if (curofs>0) curofs--;
1874
                else if (cursnd>0) cursnd--;
1875
            }
1644 helixhorne 1876
            else if (PRESSED_KEYSC(DOWN))    // scroll down
1247 helixhorne 1877
            {
2488 helixhorne 1878
                if (curofs < halfpage-1 && cursnd+curofs<g_numsounds-1)
1247 helixhorne 1879
                    curofs++;
2488 helixhorne 1880
                else if (cursnd + halfpage < g_numsounds)
1247 helixhorne 1881
                    cursnd++;
1882
            }
1644 helixhorne 1883
            else if (PRESSED_KEYSC(PGUP))    // scroll one page up
1247 helixhorne 1884
            {
2488 helixhorne 1885
                i = halfpage/2;
1886
 
1247 helixhorne 1887
                while (i>0 && curofs>0)
1888
                    i--, curofs--;
1889
                while (i>0 && cursnd>0)
1890
                    i--, cursnd--;
1891
            }
1644 helixhorne 1892
            else if (PRESSED_KEYSC(PGDN))    // scroll one page down
1247 helixhorne 1893
            {
2488 helixhorne 1894
                i = halfpage/2;
1247 helixhorne 1895
 
2488 helixhorne 1896
                while (i>0 && curofs < halfpage-1 && cursnd+curofs<g_numsounds-1)
1247 helixhorne 1897
                    i--, curofs++;
2488 helixhorne 1898
                while (i>0 && cursnd + halfpage < g_numsounds)
1247 helixhorne 1899
                    i--, cursnd++;
1900
            }
1644 helixhorne 1901
            else if (PRESSED_KEYSC(SPACE) || PRESSED_KEYSC(ENTER))   // play/stop sound
1247 helixhorne 1902
            {
1903
                int32_t j = cursnd+curofs;
1904
                int32_t k = g_sndnum[j];
1644 helixhorne 1905
 
1247 helixhorne 1906
                if (S_CheckSoundPlaying(0, k) > 0)
1907
                    S_StopSound(k);
1908
                else
1909
                    S_PlaySound(k);
1910
            }
1644 helixhorne 1911
            else if (PRESSED_KEYSC(HOME))    // goto first sound#
1247 helixhorne 1912
            {
1913
                cursnd = curofs = 0;
1914
            }
1644 helixhorne 1915
            else if (PRESSED_KEYSC(END))    // goto last sound#
1247 helixhorne 1916
            {
2488 helixhorne 1917
                if ((cursnd = g_numsounds - halfpage) >= 0)
1918
                    curofs = halfpage-1;
1247 helixhorne 1919
                else
1920
                {
1921
                    cursnd = 0;
1922
                    curofs = g_numsounds-1;
1923
                }
1924
            }
1925
 
1710 helixhorne 1926
            _printmessage16("                          FILE NAME         PITCH RANGE  PRI FLAGS VOLUME");
1927
            for (i=0; j=cursnd+i, i<SOUND_NUMDISPLINES && j<g_numsounds; i++)
1247 helixhorne 1928
            {
1710 helixhorne 1929
                int32_t l, m, k=g_sndnum[j];
1930
                sound_t *snd=&g_sounds[k];
1931
                char *cp;
1247 helixhorne 1932
 
1710 helixhorne 1933
                if (ydim-overridepm16y+28+i*9+32 >= ydim) break;
1934
 
2488 helixhorne 1935
                Bsprintf(disptext,
1710 helixhorne 1936
                         "%4d .................... ................ %6d:%-6d %3d %c%c%c%c%c %6d",
1937
                         //   5678901234567890X23456789012345678901234567
1938
                         k, snd->ps, snd->pe, snd->pr,
1939
                         snd->m&1 ? 'R':'-', snd->m&2 ? 'M':'-', snd->m&4 ? 'D':'-',
1940
                         snd->m&8 ? 'P':'-', snd->m&16 ? 'G':'-', snd->vo);
2488 helixhorne 1941
                for (l = Bsnprintf(disptext+5, 20, "%s", snd->definedname); l<20; l++)
1942
                    disptext[5+l] = ' ';
1710 helixhorne 1943
                if (snd->filename)
1944
                {
1945
                    l = Bstrlen(snd->filename);
1946
                    if (l<=16)
1947
                        cp = snd->filename;
1948
                    else
1949
                        cp = snd->filename + l-15;
2488 helixhorne 1950
                    for (m = Bsnprintf(disptext+26, 16, "%s", cp); m<16; m++)
1951
                        disptext[26+m] = ' ';
1710 helixhorne 1952
                    if (l>16)
2488 helixhorne 1953
                        disptext[26] = disptext[27] = disptext[28] = '.';
1710 helixhorne 1954
                }
1955
 
1956
                printext16(8, ydim-overridepm16y+28+i*9,
1957
                           keystatus[KEYSC_S]?editorcolors[8] : (S_CheckSoundPlaying(-1, k) ? editorcolors[2] : editorcolors[10]),
1958
                           j==cursnd+curofs ? editorcolors[1] : -1,
2488 helixhorne 1959
                           disptext, 0);
1710 helixhorne 1960
            }
1961
 
1962
            if (keystatus[KEYSC_S])    // sorting
1963
            {
1964
 
1247 helixhorne 1965
                char ch, bad=0;
1966
 
1710 helixhorne 1967
                _printmessage16("Sort by: (S)oundnum (D)ef (F)ile ori(g) or flags (12345)");
6828 terminx 1968
                videoShowFrame(1);
1710 helixhorne 1969
 
1247 helixhorne 1970
                i=0;
6827 terminx 1971
                keyFlushChars();
1247 helixhorne 1972
                while (bad == 0)
1973
                {
1486 helixhorne 1974
                    idle_waitevent();
1247 helixhorne 1975
                    if (handleevents())
1648 helixhorne 1976
                        quitevent = 0;
1247 helixhorne 1977
 
6827 terminx 1978
                    ch = keyGetChar();
1247 helixhorne 1979
 
6860 terminx 1980
                    if (keystatus[sc_Escape]) bad = 1;
1316 terminx 1981
 
1249 helixhorne 1982
                    else if (ch == 's' || ch == 'd' || ch == 'f' || ch == 'g' ||
1450 terminx 1983
                             ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5')
1247 helixhorne 1984
                    {
1985
                        bad = 2;
1249 helixhorne 1986
                        sort_sounds(ch);
1247 helixhorne 1987
                    }
1988
                }
1989
 
2488 helixhorne 1990
                clearkeys();
1247 helixhorne 1991
            }
1710 helixhorne 1992
            else
6828 terminx 1993
                videoShowFrame(1);
1247 helixhorne 1994
        }
1995
 
1996
        overridepm16y = -1;
1997
 
1998
        FX_StopAllSounds();
1999
        S_ClearSoundLocks();
2000
 
2488 helixhorne 2001
        clearkeys();
1247 helixhorne 2002
    }
2003
}
764 terminx 2004
// PK_ ^^^^
2005
 
2439 helixhorne 2006
int32_t AmbienceToggle = 1;
1296 helixhorne 2007
int32_t ParentalLock = 0;
1251 helixhorne 2008
 
7594 terminx 2009
uint8_t g_ambiencePlaying[(MAXSPRITES+7)>>3];
4300 helixhorne 2010
 
7876 terminx 2011
#define testbit(bitarray, i) (bitarray[(i)>>3] & pow2char[(i)&7])
2012
#define setbit(bitarray, i) bitarray[(i)>>3] |= pow2char[(i)&7]
2013
#define clearbit(bitarray, i) bitarray[(i)>>3] &= ~pow2char[(i)&7]
4300 helixhorne 2014
 
1251 helixhorne 2015
// adapted from actors.c
2016
static void M32_MoveFX(void)
2017
{
2018
    int32_t i, j;
2019
    int32_t x, ht;
2020
    spritetype *s;
2021
 
2022
    for (i=headspritestat[0]; i>=0; i=nextspritestat[i])
2023
    {
2024
        s = &sprite[i];
2025
 
1253 helixhorne 2026
        if (s->picnum != MUSICANDSFX)
1251 helixhorne 2027
        {
4300 helixhorne 2028
            if (testbit(g_ambiencePlaying, i))
1251 helixhorne 2029
            {
4300 helixhorne 2030
                clearbit(g_ambiencePlaying, i);
1253 helixhorne 2031
                S_StopEnvSound(s->lotag, i);
1251 helixhorne 2032
            }
1253 helixhorne 2033
        }
1722 helixhorne 2034
        else if (s->sectnum>=0)
1253 helixhorne 2035
        {
2036
            ht = s->hitag;
1251 helixhorne 2037
 
1253 helixhorne 2038
            if (s->lotag < 999 && (unsigned)sector[s->sectnum].lotag < 9 &&
1450 terminx 2039
                    AmbienceToggle && sector[s->sectnum].floorz != sector[s->sectnum].ceilingz)
1251 helixhorne 2040
            {
4055 helixhorne 2041
                if ((g_sounds[s->lotag].m & SF_MSFX))
1251 helixhorne 2042
                {
1677 terminx 2043
                    x = dist((spritetype *)&pos,s);
4300 helixhorne 2044
                    if (x < ht && !testbit(g_ambiencePlaying, i) && FX_VoiceAvailable(g_sounds[s->lotag].pr-1))
1251 helixhorne 2045
                    {
3336 hendricks2 2046
                        char om = g_sounds[s->lotag].m;
1251 helixhorne 2047
                        if (g_numEnvSoundsPlaying == NumVoices)
2048
                        {
2049
                            for (j = headspritestat[0]; j >= 0; j = nextspritestat[j])
2050
                            {
2051
                                if (s->picnum == MUSICANDSFX && j != i && sprite[j].lotag < 999 &&
4300 helixhorne 2052
                                        testbit(g_ambiencePlaying, j) && dist(&sprite[j],(spritetype *)&pos) > x)
1251 helixhorne 2053
                                {
2054
                                    S_StopEnvSound(sprite[j].lotag,j);
2055
                                    break;
2056
                                }
1316 terminx 2057
 
1251 helixhorne 2058
                            }
2059
                            if (j == -1) continue;
2060
                        }
4055 helixhorne 2061
                        g_sounds[s->lotag].m |= SF_LOOP;
1251 helixhorne 2062
                        A_PlaySound(s->lotag,i);
3336 hendricks2 2063
                        g_sounds[s->lotag].m = om;
4300 helixhorne 2064
                        setbit(g_ambiencePlaying, i);
1251 helixhorne 2065
                    }
4300 helixhorne 2066
                    if (x >= ht && testbit(g_ambiencePlaying, i))
1251 helixhorne 2067
                    {
4300 helixhorne 2068
                        clearbit(g_ambiencePlaying, i);
1251 helixhorne 2069
                        S_StopEnvSound(s->lotag,i);
2070
                    }
2071
                }
2072
            }
2073
        }
2074
    }
2075
}
2076
 
1253 helixhorne 2077
 
1644 helixhorne 2078
///__ShowHelpText__
5 Plagman 2079
 
1205 terminx 2080
void ExtShowSpriteData(int16_t spritenum)   //F6
5 Plagman 2081
{
654 terminx 2082
    UNREFERENCED_PARAMETER(spritenum);
3823 helixhorne 2083
    if (!in3dmode())
1959 helixhorne 2084
        ShowFileText("sehelp.hlp");
2085
}
5 Plagman 2086
 
2087
// Floor Over Floor (duke3d)
2088
 
2089
// If standing in sector with SE42 or SE44
2090
// then draw viewing to SE41 and raise all =hi SE43 cielings.
2091
 
2092
// If standing in sector with SE43 or SE45
2093
// then draw viewing to SE40 and lower all =hi SE42 floors.
2094
 
1644 helixhorne 2095
static int32_t fofsizex = -1;
2096
static int32_t fofsizey = -1;
649 terminx 2097
#if 0
1854 helixhorne 2098
static void ResetFOFSize(void)
5 Plagman 2099
{
2100
    if (fofsizex != -1) tilesizx[FOF] = fofsizex;
2101
    if (fofsizey != -1) tilesizy[FOF] = fofsizey;
2102
}
649 terminx 2103
#endif
1205 terminx 2104
static void ExtSE40Draw(int32_t spnum,int32_t x,int32_t y,int32_t z,int16_t a,int16_t h)
5 Plagman 2105
{
1205 terminx 2106
    static int32_t tempsectorz[MAXSECTORS];
2107
    static int32_t tempsectorpicnum[MAXSECTORS];
5 Plagman 2108
 
2079 helixhorne 2109
    int32_t j=0,k=0;
1205 terminx 2110
    int32_t floor1=0,floor2=0,ok=0,fofmode=0,draw_both=0;
2111
    int32_t offx,offy,offz;
5 Plagman 2112
 
331 terminx 2113
    if (sprite[spnum].ang!=512) return;
5 Plagman 2114
 
2115
    // Things are a little different now, as we allow for masked transparent
2116
    // floors and ceilings. So the FOF textures is no longer required
2117
    //  if (!(gotpic[FOF>>3]&(1<<(FOF&7))))
2118
    //          return;
2119
    //  gotpic[FOF>>3] &= ~(1<<(FOF&7));
2120
 
4623 terminx 2121
    if (tilesiz[562].x)
5 Plagman 2122
    {
4623 terminx 2123
        fofsizex = tilesiz[562].x;
2124
        tilesiz[562].x = 0;
5 Plagman 2125
    }
4623 terminx 2126
    if (tilesiz[562].y)
5 Plagman 2127
    {
4623 terminx 2128
        fofsizey = tilesiz[562].y;
2129
        tilesiz[562].y = 0;
5 Plagman 2130
    }
2131
 
2132
    floor1=spnum;
2133
 
331 terminx 2134
    if (sprite[spnum].lotag==42) fofmode=40;
2135
    if (sprite[spnum].lotag==43) fofmode=41;
2136
    if (sprite[spnum].lotag==44) fofmode=40;
2137
    if (sprite[spnum].lotag==45) fofmode=41;
5 Plagman 2138
 
2139
    // fofmode=sprite[spnum].lotag-2;
2140
 
2141
    // sectnum=sprite[j].sectnum;
2142
    // sectnum=cursectnum;
2143
    ok++;
2144
 
2145
    /*  recursive?
2146
    for(j=0;j<MAXSPRITES;j++)
2147
    {
2148
    if(
2149
    sprite[j].sectnum==sectnum &&
2150
    sprite[j].picnum==1 &&
2151
    sprite[j].lotag==110
1444 terminx 2152
    ) { DrawFloorOverFloor(j); break;}
5 Plagman 2153
    }
2154
    */
2155
 
2156
    // if(ok==0) { Message("no fof",RED); return; }
2157
 
1229 terminx 2158
    for (j=0; j<MAXSPRITES; j++)
5 Plagman 2159
    {
333 terminx 2160
        if (sprite[j].picnum==1 && sprite[j].lotag==fofmode && sprite[j].hitag==sprite[floor1].hitag)
5 Plagman 2161
        {
2162
            floor1=j;
2163
            fofmode=sprite[j].lotag;
2164
            ok++;
2165
            break;
2166
        }
2167
    }
2168
    // if(ok==1) { Message("no floor1",RED); return; }
2169
 
335 terminx 2170
    if (fofmode==40) k=41;
2171
    else k=40;
5 Plagman 2172
 
1229 terminx 2173
    for (j=0; j<MAXSPRITES; j++)
5 Plagman 2174
    {
333 terminx 2175
        if (sprite[j].picnum==1 && sprite[j].lotag==k && sprite[j].hitag==sprite[floor1].hitag)
5 Plagman 2176
        {
335 terminx 2177
            floor2=j;
2178
            ok++;
2179
            break;
5 Plagman 2180
        }
2181
    }
2182
 
2079 helixhorne 2183
//    i=floor1;
5 Plagman 2184
    offx=sprite[floor2].x-sprite[floor1].x;
2185
    offy=sprite[floor2].y-sprite[floor1].y;
2186
    offz=0;
2187
 
2188
    if (sprite[floor2].ang >= 1024)
2189
        offz = sprite[floor2].z;
2190
    else if (fofmode==41)
1644 helixhorne 2191
        offz = SPRITESEC(floor2).floorz;
5 Plagman 2192
    else
1644 helixhorne 2193
        offz = SPRITESEC(floor2).ceilingz;
5 Plagman 2194
 
2195
    if (sprite[floor1].ang >= 1024)
2196
        offz -= sprite[floor1].z;
2197
    else if (fofmode==40)
1644 helixhorne 2198
        offz -= SPRITESEC(floor1).floorz;
5 Plagman 2199
    else
1644 helixhorne 2200
        offz -= SPRITESEC(floor1).ceilingz;
5 Plagman 2201
 
2202
    // if(ok==2) { Message("no floor2",RED); return; }
2203
 
1229 terminx 2204
    for (j=0; j<MAXSPRITES; j++) // raise ceiling or floor
5 Plagman 2205
    {
333 terminx 2206
        if (sprite[j].picnum==1 && sprite[j].lotag==k+2 && sprite[j].hitag==sprite[floor1].hitag)
5 Plagman 2207
        {
331 terminx 2208
            if (k==40)
5 Plagman 2209
            {
1644 helixhorne 2210
                tempsectorz[sprite[j].sectnum] = SPRITESEC(j).floorz;
2211
                SPRITESEC(j).floorz += (((z-SPRITESEC(j).floorz)/32768)+1)*32768;
2212
                tempsectorpicnum[sprite[j].sectnum] = SPRITESEC(j).floorpicnum;
2213
                SPRITESEC(j).floorpicnum = 562;
5 Plagman 2214
            }
2215
            else
2216
            {
1644 helixhorne 2217
                tempsectorz[sprite[j].sectnum] = SPRITESEC(j).ceilingz;
2218
                SPRITESEC(j).ceilingz += (((z-SPRITESEC(j).ceilingz)/32768)-1)*32768;
2219
                tempsectorpicnum[sprite[j].sectnum] = SPRITESEC(j).ceilingpicnum;
2220
                SPRITESEC(j).ceilingpicnum = 562;
5 Plagman 2221
            }
2222
            draw_both = 1;
2223
        }
2224
    }
2225
 
2226
    drawrooms(x+offx,y+offy,z+offz,a,h,sprite[floor2].sectnum);
8428 hendricks2 2227
    ExtAnalyzeSprites(0,0,0,0,0);
6831 terminx 2228
    renderDrawMasks();
2350 helixhorne 2229
    M32_ResetFakeRORTiles();
5 Plagman 2230
 
2231
    if (draw_both)
2232
    {
1229 terminx 2233
        for (j=0; j<MAXSPRITES; j++) // restore ceiling or floor for the draw both sectors
5 Plagman 2234
        {
1644 helixhorne 2235
            if (sprite[j].picnum==SECTOREFFECTOR &&
1677 terminx 2236
                    sprite[j].lotag==k+2 && sprite[j].hitag==sprite[floor1].hitag)
5 Plagman 2237
            {
331 terminx 2238
                if (k==40)
5 Plagman 2239
                {
1644 helixhorne 2240
                    SPRITESEC(j).floorz = tempsectorz[sprite[j].sectnum];
2241
                    SPRITESEC(j).floorpicnum = tempsectorpicnum[sprite[j].sectnum];
5 Plagman 2242
                }
2243
                else
2244
                {
1644 helixhorne 2245
                    SPRITESEC(j).ceilingz = tempsectorz[sprite[j].sectnum];
2246
                    SPRITESEC(j).ceilingpicnum = tempsectorpicnum[sprite[j].sectnum];
5 Plagman 2247
                }
2248
            }// end if
2249
        }// end for
2250
 
2251
        // Now re-draw
2252
        drawrooms(x+offx,y+offy,z+offz,a,h,sprite[floor2].sectnum);
8428 hendricks2 2253
        ExtAnalyzeSprites(0,0,0,0,0);
6831 terminx 2254
        renderDrawMasks();
2350 helixhorne 2255
        M32_ResetFakeRORTiles();
5 Plagman 2256
    }
2257
 
2258
} // end SE40
2259
 
1205 terminx 2260
static void SE40Code(int32_t x,int32_t y,int32_t z,int32_t a,int32_t h)
5 Plagman 2261
{
1205 terminx 2262
    int32_t i;
5 Plagman 2263
 
2264
    i = 0;
331 terminx 2265
    while (i<MAXSPRITES)
5 Plagman 2266
    {
1205 terminx 2267
        int32_t t = sprite[i].lotag;
331 terminx 2268
        switch (t)
5 Plagman 2269
        {
337 terminx 2270
            //            case 40:
2271
            //            case 41:
2272
            //                ExtSE40Draw(i,x,y,z,a,h);
2273
            //                break;
2274
        case 42:
2275
        case 43:
2276
        case 44:
2277
        case 45:
2278
            if (cursectnum == sprite[i].sectnum)
2279
                ExtSE40Draw(i,x,y,z,a,h);
2280
            break;
5 Plagman 2281
        }
2282
        i++;
2283
    }
2284
}
2285
 
1205 terminx 2286
void ExtEditSectorData(int16_t sectnum)    //F7
5 Plagman 2287
{
3823 helixhorne 2288
    if (in3dmode())
5 Plagman 2289
        return;
1644 helixhorne 2290
 
727 terminx 2291
    if (eitherALT)  //ALT
5 Plagman 2292
    {
727 terminx 2293
        keystatus[KEYSC_F7] = 0;
5 Plagman 2294
        wallsprite=0;
2295
        curwall = 0;
2296
        curwallnum = 0;
2297
        cursearchspritenum = 0;
2298
        cursectornum=0;
2299
        cursector_lotag = sector[sectnum].lotag;
1644 helixhorne 2300
        cursector_lotag = getnumber16("Enter search sector lotag : ", cursector_lotag, BTAG_MAX,0);
2301
        _printmessage16("Search sector lotag %d",cursector_lotag);
5 Plagman 2302
    }
2303
    else EditSectorData(sectnum);
2304
}// end ExtEditSectorData
2305
 
1205 terminx 2306
void ExtEditWallData(int16_t wallnum)       //F8
5 Plagman 2307
{
3823 helixhorne 2308
    if (in3dmode())
5 Plagman 2309
        return;
1644 helixhorne 2310
 
727 terminx 2311
    if (eitherALT)  //ALT
5 Plagman 2312
    {
2313
        wallsprite=1;
2314
        curwall = wallnum;
2315
        curwallnum = 0;
2316
        cursearchspritenum = 0;
2317
        cursectornum = 0;
2318
        search_lotag = wall[curwall].lotag;
2319
        search_hitag = wall[curwall].hitag;
1644 helixhorne 2320
        search_lotag = getnumber16("Enter wall search lotag : ", search_lotag, BTAG_MAX,0);
2321
        search_hitag = getnumber16("Enter wall search hitag : ", search_hitag, BTAG_MAX,0);
5 Plagman 2322
        //    Bsprintf(tempbuf,"Current wall %d lo=%d hi=%d",
2323
        //             curwall,wall[curwall].lotag,wall[curwall].hitag);
1644 helixhorne 2324
        _printmessage16("Search wall lo=%d hi=%d",search_lotag,search_hitag);
5 Plagman 2325
    }
2326
    else EditWallData(wallnum);
2327
}
2328
 
1644 helixhorne 2329
static void GenericSpriteSearch(void);
1071 helixhorne 2330
 
1205 terminx 2331
void ExtEditSpriteData(int16_t spritenum)   //F8
5 Plagman 2332
{
3823 helixhorne 2333
    if (in3dmode())
5 Plagman 2334
        return;
1644 helixhorne 2335
 
727 terminx 2336
    if (eitherALT)  //ALT
1644 helixhorne 2337
        GenericSpriteSearch();
5 Plagman 2338
    else EditSpriteData(spritenum);
2339
}
2340
 
1205 terminx 2341
static inline void SpriteName(int16_t spritenum, char *lo2)
5 Plagman 2342
{
1644 helixhorne 2343
    Bstrcpy(lo2, names[sprite[spritenum].picnum]);
5 Plagman 2344
}// end SpriteName
2345
 
4336 helixhorne 2346
 
3911 helixhorne 2347
int32_t AskIfSure(const char *text)
5 Plagman 2348
{
1205 terminx 2349
    int32_t retval=1;
5 Plagman 2350
 
3823 helixhorne 2351
    if (in3dmode())
728 terminx 2352
    {
6828 terminx 2353
        videoBeginDrawing(); //{{{
728 terminx 2354
        printext256(0,0,whitecol,0,text?text:"Are you sure you want to proceed?",0);
6828 terminx 2355
        videoEndDrawing();   //}}}
728 terminx 2356
    }
2357
    else
2358
    {
1740 helixhorne 2359
        _printmessage16("%s", text?text:"Are you sure you want to proceed?");
728 terminx 2360
    }
5 Plagman 2361
 
6828 terminx 2362
    videoShowFrame(1);
5 Plagman 2363
 
727 terminx 2364
    while ((keystatus[KEYSC_ESC]|keystatus[KEYSC_ENTER]|keystatus[KEYSC_SPACE]|keystatus[KEYSC_N]) == 0)
5 Plagman 2365
    {
1648 helixhorne 2366
        idle_waitevent();
2367
 
335 terminx 2368
        if (handleevents())
2369
        {
2370
            if (quitevent)
2371
            {
377 terminx 2372
                retval = 1;
5 Plagman 2373
                break;
2374
            }
451 terminx 2375
        }
1644 helixhorne 2376
 
2377
        if (PRESSED_KEYSC(Y) || PRESSED_KEYSC(ENTER))
335 terminx 2378
        {
2379
            retval = 0;
2380
            break;
5 Plagman 2381
        }
2382
    }
1644 helixhorne 2383
 
1648 helixhorne 2384
    if (PRESSED_KEYSC(ESC))
5 Plagman 2385
        retval = 1;
1644 helixhorne 2386
 
3911 helixhorne 2387
    return retval;
5 Plagman 2388
}
2389
 
1644 helixhorne 2390
static int32_t IsValidTile(int32_t idTile)
534 terminx 2391
{
7226 terminx 2392
    // this is MAXTILES-1 because TROR uses that tile and we don't need it showing up in the tile selector, etc
7240 terminx 2393
    return (idTile>=0 && idTile<MAXTILES-1) && (tilesiz[idTile].x && tilesiz[idTile].y) && rottile[idTile].owner == -1;
534 terminx 2394
}
2395
 
1205 terminx 2396
static int32_t SelectAllTiles(int32_t iCurrentTile)
534 terminx 2397
{
1205 terminx 2398
    int32_t i;
534 terminx 2399
 
2400
    if (iCurrentTile < localartlookupnum)
2401
        iCurrentTile = localartlookup[iCurrentTile];
2402
    else
2403
        iCurrentTile = 0;
2404
 
2405
    localartlookupnum = MAXTILES;
2406
 
2407
    for (i = 0; i < MAXTILES; i++)
2408
    {
2409
        localartlookup[i] = i;
2410
        localartfreq[i] = 0;
2411
    }
2412
 
2413
    return iCurrentTile;
2414
}
2415
 
5825 terminx 2416
static int32_t OnGotoTile(int32_t tileNum);
2417
static int32_t OnSelectTile(int32_t tileNum);
1695 helixhorne 2418
static int32_t OnSaveTileGroup();
2419
static int32_t loadtilegroups(const char *fn);
1205 terminx 2420
static int32_t s_Zoom = INITIAL_ZOOM;
2421
static int32_t s_TileZoom = 1;
1695 helixhorne 2422
static char tilesel_errmsg[128], tilesel_showerr=0;
534 terminx 2423
 
1696 helixhorne 2424
static int32_t DrawTiles(int32_t iTopLeft, int32_t iSelected, int32_t nXTiles, int32_t nYTiles,
2425
                         int32_t TileDim, int32_t offset, int32_t showmsg);
534 terminx 2426
 
1695 helixhorne 2427
#define TMPERRMSG_SHOW(alsoOSD) do { \
2428
    printext256(0, 0, whitecol, 0, tilesel_errmsg, 0); \
2429
    if (alsoOSD) OSD_Printf("%s\n", tilesel_errmsg); \
2430
} while (0)
534 terminx 2431
 
1695 helixhorne 2432
#define TMPERRMSG_PRINT(Msg, ...) do {  \
1751 helixhorne 2433
    Bsprintf(tilesel_errmsg, Msg, ## __VA_ARGS__); \
1695 helixhorne 2434
    TMPERRMSG_SHOW(1); \
6828 terminx 2435
    videoShowFrame(1); \
1695 helixhorne 2436
    tilesel_showerr = 1; \
2437
} while (0)
2438
 
2439
#define TMPERRMSG_RETURN(Msg, ...) do   \
2440
{ \
1751 helixhorne 2441
    TMPERRMSG_PRINT(Msg, ## __VA_ARGS__);  \
1695 helixhorne 2442
    return 1; \
2443
} while (0)
2444
 
2445
 
3302 helixhorne 2446
static inline void pushDisableFog(void)
2447
{
2448
#ifdef USE_OPENGL
6829 terminx