Subversion Repositories eduke32

Rev

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