Comment: | More style fixes |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
c634a689e76e7c60fb8b685ea40cb999 |
User & Date: | js on 2025-03-29 17:13:40 |
Other Links: | manifest | tags |
2025-03-29
| ||
22:29 | Add variables with a getter / setter block check-in: cd2ac12a14 user: js tags: trunk | |
17:13 | More style fixes check-in: c634a689e7 user: js tags: trunk | |
14:25 | Switch from clang-format to manual formatting check-in: 75e920ae30 user: js tags: trunk | |
Modified src/Alias.h from [0fb6418ce5] to [c03f900e5c].
1 2 3 4 5 6 7 8 9 | #import "Identifier.h" OF_ASSUME_NONNULL_BEGIN @interface Alias: Identifier @property (direct, copy, nonatomic) OFString *action; @property (readonly, nonatomic) bool persisted; + (instancetype)aliasWithName: (OFString *)name | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #import "Identifier.h" OF_ASSUME_NONNULL_BEGIN @interface Alias: Identifier @property (direct, copy, nonatomic) OFString *action; @property (readonly, nonatomic) bool persisted; + (instancetype)aliasWithName: (OFString *)name action: (OFString *)action persisted: (bool)persisted OF_DIRECT; - (instancetype)initWithName: (OFString *)name OF_UNAVAILABLE; - (instancetype)initWithName: (OFString *)name action: (OFString *)action persisted: (bool)persisted OF_DESIGNATED_INITIALIZER OF_DIRECT; @end OF_ASSUME_NONNULL_END |
Modified src/Alias.m from [fe2a009013] to [99fa37b5c7].
1 2 3 4 | #import "Alias.h" @implementation Alias + (instancetype)aliasWithName: (OFString *)name | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #import "Alias.h" @implementation Alias + (instancetype)aliasWithName: (OFString *)name action: (OFString *)action persisted: (bool)persisted; { return [[self alloc] initWithName: name action: action persisted: persisted]; } - (instancetype)initWithName: (OFString *)name action: (OFString *)action persisted: (bool)persisted { self = [super initWithName: name]; _action = [action copy]; _persisted = persisted; return self; |
︙ | ︙ |
Modified src/Command.h from [f6eb8c644d] to [4155619926].
1 2 3 4 | #import "Identifier.h" OF_ASSUME_NONNULL_BEGIN | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #import "Identifier.h" OF_ASSUME_NONNULL_BEGIN #define COMMAND(name, nargs, block_) \ OF_CONSTRUCTOR() \ { \ enqueueInit(^ { \ Identifier.identifiers[@#name] = [Command \ commandWithName: @#name \ argumentsTypes: nargs \ block: block_]; \ }); \ } OF_DIRECT_MEMBERS @interface Command: Identifier @property (readonly, nonatomic) int argumentsTypes; + (instancetype)commandWithName: (OFString *)name argumentsTypes: (int)argumentsTypes block: (id)block; - (instancetype)initWithName: (OFString *)name OF_UNAVAILABLE; - (instancetype)initWithName: (OFString *)name argumentsTypes: (int)argumentsTypes block: (id)block OF_DESIGNATED_INITIALIZER; - (int)callWithArguments: (OFArray<OFString *> *)arguments isDown: (bool)isDown; @end OF_ASSUME_NONNULL_END |
Modified src/Command.m from [254356cb16] to [5f400a60e2].
︙ | ︙ | |||
21 22 23 24 25 26 27 | @implementation Command { id _block; } + (instancetype)commandWithName: (OFString *)name | | | | | | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | @implementation Command { id _block; } + (instancetype)commandWithName: (OFString *)name argumentsTypes: (int)argumentsTypes block: (id)block { return [[self alloc] initWithName: name argumentsTypes: argumentsTypes block: block]; } - (instancetype)initWithName: (OFString *)name argumentsTypes: (int)argumentsTypes block: (id)block { self = [super initWithName: name]; _argumentsTypes = argumentsTypes; _block = block; return self; |
︙ | ︙ |
Modified src/Cube.m from [67dd855e73] to [4173147859].
︙ | ︙ | |||
123 124 125 126 127 128 129 | _height = 1080; } } log(@"video: mode"); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if ((_window = SDL_CreateWindow("cube engine", | | < | | < | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | _height = 1080; } } log(@"video: mode"); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if ((_window = SDL_CreateWindow("cube engine", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _width, _height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | (!windowed ? SDL_WINDOW_FULLSCREEN : 0))) == NULL || SDL_GL_CreateContext(_window) == NULL) fatal(@"Unable to create OpenGL screen"); log(@"video: misc"); SDL_SetWindowGrab(_window, SDL_TRUE); SDL_SetRelativeMouseMode(SDL_TRUE); SDL_ShowCursor(0); |
︙ | ︙ | |||
240 241 242 243 244 245 246 | [self quit]; break; case SDL_KEYDOWN: case SDL_KEYUP: if (_repeatsKeys || event.key.repeat == 0) keypress(event.key.keysym.sym, | | | | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | [self quit]; break; case SDL_KEYDOWN: case SDL_KEYUP: if (_repeatsKeys || event.key.repeat == 0) keypress(event.key.keysym.sym, (event.key.state == SDL_PRESSED)); break; case SDL_TEXTINPUT: input(@(event.text.text)); break; case SDL_MOUSEMOTION: if (ignore) { ignore--; |
︙ | ︙ | |||
301 302 303 304 305 306 307 | - (void)screenshot { SDL_Surface *image; SDL_Surface *temp; if ((image = SDL_CreateRGBSurface(SDL_SWSURFACE, _width, _height, 24, | | | < | | < | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | - (void)screenshot { SDL_Surface *image; SDL_Surface *temp; if ((image = SDL_CreateRGBSurface(SDL_SWSURFACE, _width, _height, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0)) != NULL) { if ((temp = SDL_CreateRGBSurface(SDL_SWSURFACE, _width, _height, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0)) != NULL) { glReadPixels(0, 0, _width, _height, GL_RGB, GL_UNSIGNED_BYTE, image->pixels); for (int idx = 0; idx < _height; idx++) { char *dest = (char *)temp->pixels + 3 * _width * idx; memcpy(dest, (char *)image->pixels + 3 * _width * (_height - 1 - idx), 3 * _width); endianswap(dest, 3, _width); } OFString *path = [OFString stringWithFormat: @"screenshots/screenshot_%d.bmp", lastmillis]; SDL_SaveBMP(temp, [_userDataIRI IRIByAppendingPathComponent: path] |
︙ | ︙ | |||
343 344 345 346 347 348 349 | // failure exit void fatal(OFConstantString *s, ...) { va_list args; va_start(args, s); OFMutableString *msg = [[OFMutableString alloc] initWithFormat: s | | | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | // failure exit void fatal(OFConstantString *s, ...) { va_list args; va_start(args, s); OFMutableString *msg = [[OFMutableString alloc] initWithFormat: s arguments: args]; va_end(args); [msg appendFormat: @" (%s)\n", SDL_GetError()]; [Cube.sharedInstance showMessage: msg]; [OFApplication terminateWithStatus: 1]; } |
︙ | ︙ |
Modified src/MD2.h from [25323c6c56] to [af445ff14a].
︙ | ︙ | |||
10 11 12 13 14 15 16 | @property (copy, nonatomic) OFString *loadname; @property (nonatomic) int mdlnum; @property (nonatomic) bool loaded; + (instancetype)md2; - (bool)loadWithIRI: (OFIRI *)IRI; - (void)renderWithLight: (OFColor *)light | | | | | | | | | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @property (copy, nonatomic) OFString *loadname; @property (nonatomic) int mdlnum; @property (nonatomic) bool loaded; + (instancetype)md2; - (bool)loadWithIRI: (OFIRI *)IRI; - (void)renderWithLight: (OFColor *)light frame: (int)frame range: (int)range position: (OFVector3D)position yaw: (float)yaw pitch: (float)pitch scale: (float)scale speed: (float)speed snap: (int)snap basetime: (int)basetime; - (void)scaleWithFrame: (int)frame scale: (float)scale snap: (int)snap; @end OF_ASSUME_NONNULL_END |
Modified src/MD2.m from [64d68c27a0] to [c2a1e1b6fe].
︙ | ︙ | |||
65 66 67 68 69 70 71 | - (bool)loadWithIRI: (OFIRI *)IRI { OFSeekableStream *stream; @try { stream = (OFSeekableStream *)[[OFIRIHandler handlerForIRI: IRI] openItemAtIRI: IRI | | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | - (bool)loadWithIRI: (OFIRI *)IRI { OFSeekableStream *stream; @try { stream = (OFSeekableStream *)[[OFIRIHandler handlerForIRI: IRI] openItemAtIRI: IRI mode: @"r"]; } @catch (id e) { return false; } if (![stream isKindOfClass: OFSeekableStream.class]) return false; |
︙ | ︙ | |||
88 89 90 91 92 93 94 | _frames = OFAllocMemory(header.numFrames, header.frameSize); } @catch (OFOutOfMemoryException *e) { return false; } [stream seekToOffset: header.offsetFrames whence: OFSeekSet]; [stream readIntoBuffer: _frames | | | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | _frames = OFAllocMemory(header.numFrames, header.frameSize); } @catch (OFOutOfMemoryException *e) { return false; } [stream seekToOffset: header.offsetFrames whence: OFSeekSet]; [stream readIntoBuffer: _frames exactLength: header.frameSize * header.numFrames]; for (int i = 0; i < header.numFrames; ++i) endianswap(_frames + i * header.frameSize, sizeof(float), 6); @try { _glCommands = OFAllocMemory(header.numGlCommands, sizeof(int)); } @catch (OFOutOfMemoryException *e) { return false; } [stream seekToOffset: header.offsetGlCommands whence: OFSeekSet]; [stream readIntoBuffer: _glCommands exactLength: header.numGlCommands * sizeof(int)]; endianswap(_glCommands, sizeof(int), header.numGlCommands); _numFrames = header.numFrames; _numGlCommands = header.numGlCommands; _frameSize = header.frameSize; _numTriangles = header.numTriangles; _numVerts = header.numVertices; |
︙ | ︙ | |||
136 137 138 139 140 141 142 | v->y = -(snap(sn, cv[1] * cf->scale[1]) + cf->translate[1]) / sc; v->z = (snap(sn, cv[2] * cf->scale[2]) + cf->translate[2]) / sc; } } - (void)renderWithLight: (OFColor *)light | | | | | | | | | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | v->y = -(snap(sn, cv[1] * cf->scale[1]) + cf->translate[1]) / sc; v->z = (snap(sn, cv[2] * cf->scale[2]) + cf->translate[2]) / sc; } } - (void)renderWithLight: (OFColor *)light frame: (int)frame range: (int)range position: (OFVector3D)position yaw: (float)yaw pitch: (float)pitch scale: (float)sc speed: (float)speed snap: (int)sn basetime: (int)basetime { for (int i = 0; i < range; i++) if (!_mverts[frame + i]) [self scaleWithFrame: frame + i scale: sc snap: sn]; glPushMatrix(); glTranslatef(position.x, position.y, position.z); |
︙ | ︙ |
Modified src/MapModelInfo.h from [9966a1ab68] to [1a4824d0f9].
1 2 3 4 5 6 7 8 9 10 | #import <ObjFW/ObjFW.h> OF_ASSUME_NONNULL_BEGIN OF_DIRECT_MEMBERS @interface MapModelInfo: OFObject @property (nonatomic) int rad, h, zoff, snap; @property (copy, nonatomic) OFString *name; + (instancetype)infoWithRad: (int)rad | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #import <ObjFW/ObjFW.h> OF_ASSUME_NONNULL_BEGIN OF_DIRECT_MEMBERS @interface MapModelInfo: OFObject @property (nonatomic) int rad, h, zoff, snap; @property (copy, nonatomic) OFString *name; + (instancetype)infoWithRad: (int)rad h: (int)h zoff: (int)zoff snap: (int)snap name: (OFString *)name; - (instancetype)init OF_UNAVAILABLE; - (instancetype)initWithRad: (int)rad h: (int)h zoff: (int)zoff snap: (int)snap name: (OFString *)name; @end OF_ASSUME_NONNULL_END |
Modified src/MapModelInfo.m from [19135ee4c2] to [bd54b60804].
1 2 3 4 | #import "MapModelInfo.h" @implementation MapModelInfo + (instancetype)infoWithRad: (int)rad | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #import "MapModelInfo.h" @implementation MapModelInfo + (instancetype)infoWithRad: (int)rad h: (int)h zoff: (int)zoff snap: (int)snap name: (OFString *)name { return [[self alloc] initWithRad: rad h: h zoff: zoff snap: snap name: name]; } - (instancetype)initWithRad: (int)rad h: (int)h zoff: (int)zoff snap: (int)snap name: (OFString *)name { self = [super init]; _rad = rad; _h = h; _zoff = zoff; _snap = snap; |
︙ | ︙ |
Modified src/Monster.h from [ecb02516a6] to [09f03dc0a4].
︙ | ︙ | |||
23 24 25 26 27 28 29 | + (void)restoreAll; + (void)resetAll; + (void)thinkAll; + (void)renderAll; // TODO: Move this somewhere else + (void)endSinglePlayerWithAllKilled: (bool)allKilled; + (instancetype)monsterWithType: (int)type | | | | | | | | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | + (void)restoreAll; + (void)resetAll; + (void)thinkAll; + (void)renderAll; // TODO: Move this somewhere else + (void)endSinglePlayerWithAllKilled: (bool)allKilled; + (instancetype)monsterWithType: (int)type yaw: (int)yaw state: (int)state trigger: (int)trigger move: (int)move; - (instancetype)initWithType: (int)type yaw: (int)yaw state: (int)state trigger: (int)trigger move: (int)move; - (void)incurDamage: (int)damage fromEntity: (__kindof DynamicEntity *)d; @end |
Modified src/Monster.m from [911d4fb855] to [aa7be47ff2].
︙ | ︙ | |||
19 20 21 22 23 24 25 | + (OFMutableArray<Monster *> *)monsters { return monsters; } + (instancetype)monsterWithType: (int)type | | | | | | | | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | + (OFMutableArray<Monster *> *)monsters { return monsters; } + (instancetype)monsterWithType: (int)type yaw: (int)yaw state: (int)state trigger: (int)trigger move: (int)move { return [[self alloc] initWithType: type yaw: yaw state: state trigger: trigger move: move]; } VARF(skill, 1, 3, 10, conoutf(@"skill is now %d", skill)); // for savegames + (void)restoreAll { |
︙ | ︙ | |||
72 73 74 75 76 77 78 | { GUN_ICEBALL, 12, 250, 1, 0, 10, 400, 6, 18, 18, S_PAINH, S_DEATHH, @"a knight", @"monster/knight" }, { GUN_SLIMEBALL, 15, 100, 1, 0, 200, 400, 2, 13, 10, S_PAIND, S_DEATHD, @"a goblin", @"monster/goblin" }, }; - (instancetype)initWithType: (int)type | | | | | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | { GUN_ICEBALL, 12, 250, 1, 0, 10, 400, 6, 18, 18, S_PAINH, S_DEATHH, @"a knight", @"monster/knight" }, { GUN_SLIMEBALL, 15, 100, 1, 0, 200, 400, 2, 13, 10, S_PAIND, S_DEATHD, @"a goblin", @"monster/goblin" }, }; - (instancetype)initWithType: (int)type yaw: (int)yaw state: (int)state trigger: (int)trigger move: (int)move { self = [super init]; if (type >= NUMMONSTERTYPES) { conoutf(@"warning: unknown monster in spawn: %d", type); type = 0; } |
︙ | ︙ | |||
168 169 170 171 172 173 174 | mtimestart = lastmillis; for (Entity *e in ents) { if (e.type != MONSTER) continue; Monster *m = [Monster monsterWithType: e.attr2 | | | | | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | mtimestart = lastmillis; for (Entity *e in ents) { if (e.type != MONSTER) continue; Monster *m = [Monster monsterWithType: e.attr2 yaw: e.attr1 state: M_SLEEP trigger: 100 move: 0]; m.origin = OFMakeVector3D(e.x, e.y, e.z); [monsters addObject: m]; entinmap(m); monstertotal++; } } } |
︙ | ︙ | |||
285 286 287 288 289 290 291 | self.jumpNext = true; // search for a way around (common) else if (self.trigger < lastmillis && (self.monsterState != M_HOME || !rnd(5))) { // patented "random walk" AI pathfinding (tm) ;) self.targetYaw += 180 + rnd(180); [self transitionWithState: M_SEARCH | | | | | < < | | < | | | | | | | | | | | | | | | < | | | | | | | | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 | self.jumpNext = true; // search for a way around (common) else if (self.trigger < lastmillis && (self.monsterState != M_HOME || !rnd(5))) { // patented "random walk" AI pathfinding (tm) ;) self.targetYaw += 180 + rnd(180); [self transitionWithState: M_SEARCH moving: 1 n: 400 r: 1000]; } } float enemyYaw = -(float)atan2(self.enemy.origin.x - self.origin.x, self.enemy.origin.y - self.origin.y) / PI * 180 + 180; switch (self.monsterState) { case M_PAIN: case M_ATTACKING: case M_SEARCH: if (self.trigger < lastmillis) [self transitionWithState: M_HOME moving: 1 n: 100 r: 200]; break; // state classic sp monster start in, wait for visual contact case M_SLEEP: { OFVector3D target; if (editmode || !enemylos(self, &target)) return; // skip running physics [self normalizeWithAngle: enemyYaw]; float angle = (float)fabs(enemyYaw - self.yaw); // the better the angle to the player, the further the monster // can see/hear if (disttoenemy < 8 || (disttoenemy < 16 && angle < 135) || (disttoenemy < 32 && angle < 90) || (disttoenemy < 64 && angle < 45) || angle < 10) { [self transitionWithState: M_HOME moving: 1 n: 500 r: 200]; OFVector3D loc = self.origin; playsound(S_GRUNT1 + rnd(2), &loc); } break; } case M_AIMING: // this state is the delay between wanting to shoot and actually // firing if (self.trigger < lastmillis) { self.lastAction = 0; self.attacking = true; shoot(self, self.attackTarget); [self transitionWithState: M_ATTACKING moving: 0 n: 600 r: 0]; } break; case M_HOME: // monster has visual contact, heads straight for player and // may want to shoot at any time self.targetYaw = enemyYaw; if (self.trigger < lastmillis) { OFVector3D target; if (!enemylos(self, &target)) { // no visual contact anymore, let monster get // as close as possible then search for player [self transitionWithState: M_HOME moving: 1 n: 800 r: 500]; } else { // the closer the monster is the more likely he // wants to shoot if (!rnd((int)disttoenemy / 3 + 1) && self.enemy.state == CS_ALIVE) { // get ready to fire self.attackTarget = target; int n = monstertypes[self.monsterType].lag; [self transitionWithState: M_AIMING moving: 0 n: n r: 10]; } else { // track player some more int n = monstertypes[self.monsterType].rate; [self transitionWithState: M_HOME moving: 1 n: n r: 0]; } } } break; } moveplayer(self, 1, false); // use physics to move monster } - (void)incurDamage: (int)damage fromEntity: (__kindof DynamicEntity *)d { // a monster hit us if ([d isKindOfClass: Monster.class]) { Monster *m = (Monster *)d; // guard for RL guys shooting themselves :) if (self != m) { // don't attack straight away, first get angry self.anger++; int anger = (self.monsterType == m.monsterType ? self.anger / 2 : self.anger); if (anger >= monstertypes[self.monsterType].loyalty) // monster infight if very angry self.enemy = m; } } else { // player hit us self.anger = 0; self.enemy = d; } // in this state monster won't attack [self transitionWithState: M_PAIN moving: 0 n: monstertypes[self.monsterType].pain r: 200]; if ((self.health -= damage) <= 0) { self.state = CS_DEAD; self.lastAction = lastmillis; numkilled++; Player.player1.frags = numkilled; OFVector3D loc = self.origin; playsound(monstertypes[self.monsterType].diesound, &loc); int remain = monstertotal - numkilled; if (remain > 0 && remain <= 5) conoutf(@"only %d monster(s) remaining", remain); } else { OFVector3D loc = self.origin; playsound(monstertypes[self.monsterType].painsound, &loc); } } + (void)endSinglePlayerWithAllKilled: (bool)allKilled { conoutf(allKilled ? @"you have cleared the map!" : @"you reached the exit!"); conoutf(@"score: %d kills in %d seconds", numkilled, (lastmillis - mtimestart) / 1000); monstertotal = 0; startintermission(); } + (void)thinkAll |
︙ | ︙ |
Modified src/Variable.h from [780b5706d6] to [237ce5cd40].
1 2 3 4 5 6 7 8 9 10 | #import "Identifier.h" OF_ASSUME_NONNULL_BEGIN #define VARP(name, min_, cur, max_) \ int name = cur; \ \ OF_CONSTRUCTOR() \ { \ enqueueInit(^ { \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #import "Identifier.h" OF_ASSUME_NONNULL_BEGIN #define VARP(name, min_, cur, max_) \ int name = cur; \ \ OF_CONSTRUCTOR() \ { \ enqueueInit(^ { \ Variable *variable = [Variable \ variableWithName: @#name \ min: min_ \ max: max_ \ storage: &name \ function: NULL \ persisted: true]; \ Identifier.identifiers[@#name] = variable; \ }); \ } #define VAR(name, min_, cur, max_) \ int name = cur; \ \ OF_CONSTRUCTOR() \ { \ enqueueInit(^ { \ Variable *variable = [Variable \ variableWithName: @#name \ min: min_ \ max: max_ \ storage: &name \ function: NULL \ persisted: false]; \ Identifier.identifiers[@#name] = variable; \ }); \ } #define VARF(name, min_, cur, max_, body) \ static void var_##name(void); \ static int name = cur; \ \ OF_CONSTRUCTOR() \ { \ enqueueInit(^ { \ Variable *variable = [Variable \ variableWithName: @#name \ min: min_ \ max: max_ \ storage: &name \ function: var_##name \ persisted: false]; \ Identifier.identifiers[@#name] = variable; \ }); \ } \ \ static void \ var_##name(void) \ { \ body; \ } #define VARFP(name, min_, cur, max_, body) \ static void var_##name(void); \ static int name = cur; \ \ OF_CONSTRUCTOR() \ { \ enqueueInit(^ { \ Variable *variable = [Variable \ variableWithName: @#name \ min: min_ \ max: max_ \ storage: &name \ function: var_##name \ persisted: true]; \ Identifier.identifiers[@#name] = variable; \ }); \ } \ \ static void \ var_##name(void) \ { \ body; \ } @interface Variable: Identifier @property (direct, readonly, nonatomic) int min, max; @property (direct, readonly, nonatomic) int *storage; @property (direct, readonly, nullable, nonatomic) void (*function)(); @property (readonly, nonatomic) bool persisted; + (instancetype)variableWithName: (OFString *)name min: (int)min max: (int)max storage: (int *)storage function: (void (*_Nullable)())function persisted: (bool)persisted OF_DIRECT; - (instancetype)initWithName: (OFString *)name OF_UNAVAILABLE; - (instancetype)initWithName: (OFString *)name min: (int)min max: (int)max storage: (int *)storage function: (void (*_Nullable)())function persisted: (bool)persisted OF_DESIGNATED_INITIALIZER OF_DIRECT; - (void)printValue OF_DIRECT; - (void)setValue: (int)value OF_DIRECT; @end OF_ASSUME_NONNULL_END |
Modified src/Variable.m from [60a145c003] to [892ebc7d62].
1 2 3 4 5 6 | #import "Variable.h" #include "cube.h" @implementation Variable + (instancetype)variableWithName: (OFString *)name | | | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #import "Variable.h" #include "cube.h" @implementation Variable + (instancetype)variableWithName: (OFString *)name min: (int)min max: (int)max storage: (int *)storage function: (void (*__cdecl)())function persisted: (bool)persisted { return [[self alloc] initWithName: name min: min max: max storage: storage function: function persisted: persisted]; } - (instancetype)initWithName: (OFString *)name min: (int)min max: (int)max storage: (int *)storage function: (void (*__cdecl)())function persisted: (bool)persisted { self = [super initWithName: name]; _min = min; _max = max; _storage = storage; _function = function; |
︙ | ︙ |
Modified src/clientextras.m from [d459541c88] to [84515fc725].
1 2 3 4 5 6 7 8 9 10 11 12 | // clientextras.cpp: stuff that didn't fit in client.cpp or clientgame.cpp :) #include "cube.h" #import "Command.h" #import "Monster.h" #import "Player.h" // render players & monsters // very messy ad-hoc handling of animation frames, should be made more // configurable | | | > | | > > | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | // clientextras.cpp: stuff that didn't fit in client.cpp or clientgame.cpp :) #include "cube.h" #import "Command.h" #import "Monster.h" #import "Player.h" // render players & monsters // very messy ad-hoc handling of animation frames, should be made more // configurable // D D D D' D D D D' A A' P P' I I' // R, R' E L J J' int frame[] = { 178, 184, 190, 137, 183, 189, 197, 164, 46, 51, 54, 32, 0, 0, 40, 1, 162, 162, 67, 168 }; int range[] = { 6, 6, 8, 28, 1, 1, 1, 1, 8, 19, 4, 18, 40, 1, 6, 15, 1, 1, 1, 1 }; void renderclient( DynamicEntity *d, bool team, OFString *mdlname, bool hellpig, float scale) { int n = 3; float speed = 100.0f; |
︙ | ︙ |
Modified src/clientgame.m from [0b8b0d202d] to [418707bf92].
︙ | ︙ | |||
309 310 311 312 313 314 315 | // let armour absorb when possible int ad = damage * (player1.armourType + 1) * 20 / 100; if (ad > Player.player1.armour) ad = Player.player1.armour; player1.armour -= ad; damage -= ad; float droll = damage / 0.5f; | > | < < < | < < | < | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | // let armour absorb when possible int ad = damage * (player1.armourType + 1) * 20 / 100; if (ad > Player.player1.armour) ad = Player.player1.armour; player1.armour -= ad; damage -= ad; float droll = damage / 0.5f; // give player a kick depending on amount of damage player1.roll += player1.roll > 0 ? droll : (player1.roll < 0 ? -droll : (rnd(2) ? droll : -droll)); if ((player1.health -= damage) <= 0) { if (actor == -2) { conoutf(@"you got killed by %@!", act.name); } else if (actor == -1) { actor = getclientnum(); conoutf(@"you suicided!"); addmsg(1, 2, SV_FRAGS, --player1.frags); } else { Player *a = getclient(actor); if (a != nil) { if (isteam(a.team, player1.team)) conoutf(@"you got fragged by a " @"teammate (%@)", a.name); else conoutf( @"you got fragged by %@", a.name); } } showscores(true); addmsg(1, 2, SV_DIED, actor); |
︙ | ︙ |
Modified src/clients.m from [0b6e5b2153] to [895b86000b].
︙ | ︙ | |||
39 40 41 42 43 44 45 | if (!allow) conoutf(@"editing in multiplayer requires coopedit mode (1)"); return allow; } VARF(rate, 0, 0, 25000, | | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | if (!allow) conoutf(@"editing in multiplayer requires coopedit mode (1)"); return allow; } VARF(rate, 0, 0, 25000, if (clienthost && (!rate || rate > 1000)) enet_host_bandwidth_limit(clienthost, rate, rate)); void throttle(); VARF(throttle_interval, 0, 5, 30, throttle()); VARF(throttle_accel, 0, 2, 32, throttle()); VARF(throttle_decel, 0, 2, 32, throttle()); |
︙ | ︙ | |||
212 213 214 215 216 217 218 | msgsizelookup(type)); if (messages.count == 100) { conoutf(@"command flood protection (type %d)", type); return; } OFMutableData *msg = [OFMutableData dataWithItemSize: sizeof(int) | | | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | msgsizelookup(type)); if (messages.count == 100) { conoutf(@"command flood protection (type %d)", type); return; } OFMutableData *msg = [OFMutableData dataWithItemSize: sizeof(int) capacity: num + 2]; [msg addItem: &num]; [msg addItem: &rel]; [msg addItem: &type]; va_list marker; va_start(marker, type); for (int i = 0; i < num - 1; i++) { |
︙ | ︙ |
Modified src/clients2c.m from [11f87c82e6] to [9597798812].
︙ | ︙ | |||
41 42 43 44 45 46 47 | Player *player1 = Player.player1; const float r = player1.radius + d.radius; const float dx = player1.origin.x - d.origin.x; const float dy = player1.origin.y - d.origin.y; const float dz = player1.origin.z - d.origin.z; const float rz = player1.aboveEye + d.eyeHeight; const float fx = (float)fabs(dx), fy = (float)fabs(dy), | | | < | | < | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | Player *player1 = Player.player1; const float r = player1.radius + d.radius; const float dx = player1.origin.x - d.origin.x; const float dy = player1.origin.y - d.origin.y; const float dz = player1.origin.z - d.origin.z; const float rz = player1.aboveEye + d.eyeHeight; const float fx = (float)fabs(dx), fy = (float)fabs(dy), fz = (float)fabs(dz); if (fx < r && fy < r && fz < rz && d.state != CS_DEAD) { if (fx < fy) // push aside d.origin = OFAddVectors3D(d.origin, OFMakeVector3D( 0, (dy < 0 ? r - fy : -(r - fy)), 0)); else d.origin = OFAddVectors3D(d.origin, OFMakeVector3D( (dx < 0 ? r - fx : -(r - fx)), 0, 0)); } int lagtime = lastmillis - d.lastUpdate; if (lagtime) { d.lag = (d.lag * 5 + lagtime) / 6; d.lastUpdate = lastmillis; } } |
︙ | ︙ | |||
83 84 85 86 87 88 89 | switch (type = getint(&p)) { case SV_INITS2C: // welcome messsage from the server { cn = getint(&p); int prot = getint(&p); if (prot != PROTOCOL_VERSION) { conoutf(@"you are using a different game " | | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | switch (type = getint(&p)) { case SV_INITS2C: // welcome messsage from the server { cn = getint(&p); int prot = getint(&p); if (prot != PROTOCOL_VERSION) { conoutf(@"you are using a different game " @"protocol (you: %d, server: %d)", PROTOCOL_VERSION, prot); disconnect(false, false); return; } toservermap = @""; clientnum = cn; // we are now fully connected if (!getint(&p)) // we are the first client on this server, set // map toservermap = getclientmap(); sgetstr(); if (text[0] && strcmp(text, clientpassword.UTF8String)) { conoutf(@"you need to set the correct password " @"to join this server!"); disconnect(false, false); return; } if (getint(&p) == 1) conoutf(@"server is FULL, disconnecting.."); break; } |
︙ | ︙ | |||
261 262 263 264 265 266 267 | addmsg(1, 2, SV_FRAGS, (Player.player1.frags += frags)); } else { Player *a = getclient(actor); if (a != nil) { if (isteam(a.team, d.name)) conoutf(@"%@ fragged his " | | | | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | addmsg(1, 2, SV_FRAGS, (Player.player1.frags += frags)); } else { Player *a = getclient(actor); if (a != nil) { if (isteam(a.team, d.name)) conoutf(@"%@ fragged his " @"teammate (%@)", a.name, d.name); else conoutf(@"%@ fragged %@", a.name, d.name); } } OFVector3D loc = d_.origin; playsound(S_DIE1 + rnd(2), &loc); |
︙ | ︙ | |||
299 300 301 302 303 304 305 | break; } // server acknowledges that I picked up this item case SV_ITEMACC: realpickup(getint(&p), Player.player1); break; | | | > | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | break; } // server acknowledges that I picked up this item case SV_ITEMACC: realpickup(getint(&p), Player.player1); break; // coop editing messages, should be extended to include all // possible editing ops case SV_EDITH: case SV_EDITT: case SV_EDITS: case SV_EDITD: case SV_EDITE: { int x = getint(&p); int y = getint(&p); int xs = getint(&p); |
︙ | ︙ | |||
363 364 365 366 367 368 369 | case SV_PING: getint(&p); break; case SV_PONG: addmsg(0, 2, SV_CLIENTPING, Player.player1.ping = (Player.player1.ping * 5 + | | < | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | case SV_PING: getint(&p); break; case SV_PONG: addmsg(0, 2, SV_CLIENTPING, Player.player1.ping = (Player.player1.ping * 5 + lastmillis - getint(&p)) / 6); break; case SV_CLIENTPING: OFAssert([players[cn] isKindOfClass: Player.class]); ((Player *)players[cn]).ping = getint(&p); break; |
︙ | ︙ | |||
397 398 399 400 401 402 403 | } case SV_SERVMSG: sgetstr(); conoutf(@"%s", text); break; | | | < > | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | } case SV_SERVMSG: sgetstr(); conoutf(@"%s", text); break; // so we can messages without breaking previous // clients/servers, if necessary case SV_EXT: { for (int n = getint(&p); n; n--) getint(&p); break; } default: neterr(@"type"); return; } } |
Modified src/commands.m from [e072f98aae] to [e486b084f6].
︙ | ︙ | |||
18 19 20 21 22 23 24 | void alias(OFString *name, OFString *action) { Alias *alias = Identifier.identifiers[name]; if (alias == nil) Identifier.identifiers[name] = [Alias aliasWithName: name | | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | void alias(OFString *name, OFString *action) { Alias *alias = Identifier.identifiers[name]; if (alias == nil) Identifier.identifiers[name] = [Alias aliasWithName: name action: action persisted: true]; else { if ([alias isKindOfClass: Alias.class]) alias.action = action; else conoutf( @"cannot redefine builtin %@ with an alias", name); } |
︙ | ︙ |
Modified src/console.m from [1d463d8f9f] to [a781a15ab9].
︙ | ︙ | |||
58 59 60 61 62 63 64 | void conoutf(OFConstantString *format, ...) { va_list arguments; va_start(arguments, format); OFString *string = [[OFString alloc] initWithFormat: format | | | | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | void conoutf(OFConstantString *format, ...) { va_list arguments; va_start(arguments, format); OFString *string = [[OFString alloc] initWithFormat: format arguments: arguments]; va_end(arguments); int n = 0; while (string.length > WORDWRAP) { conline([string substringToIndex: WORDWRAP], n++ != 0); string = [string substringFromIndex: WORDWRAP]; } conline(string, n != 0); } // render buffer taking into account time & scrolling void renderconsole() { int nd = 0; OFString *refs[ndraw]; size_t i = 0; for (ConsoleLine *conline in conlines) { if (conskip ? i >= conskip - 1 || i >= conlines.count - ndraw : lastmillis - conline.outtime < 20000) { refs[nd++] = conline.text; if (nd == ndraw) break; } i++; } |
︙ | ︙ | |||
103 104 105 106 107 108 109 | static OFMutableArray<KeyMapping *> *keyMappings = nil; COMMAND(keymap, ARG_3STR, ^ (OFString *code, OFString *key, OFString *action) { if (keyMappings == nil) keyMappings = [[OFMutableArray alloc] init]; KeyMapping *mapping = [KeyMapping mappingWithCode: code.cube_intValue | | | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | static OFMutableArray<KeyMapping *> *keyMappings = nil; COMMAND(keymap, ARG_3STR, ^ (OFString *code, OFString *key, OFString *action) { if (keyMappings == nil) keyMappings = [[OFMutableArray alloc] init]; KeyMapping *mapping = [KeyMapping mappingWithCode: code.cube_intValue name: key]; mapping.action = action; [keyMappings addObject: mapping]; }) COMMAND(bind, ARG_2STR, ^ (OFString *key, OFString *action) { for (KeyMapping *mapping in keyMappings) { if ([mapping.name caseInsensitiveCompare: key] == |
︙ | ︙ | |||
181 182 183 184 185 186 187 | case SDLK_RETURN: break; case SDLK_BACKSPACE: case SDLK_LEFT: if (commandbuf.length > 0) [commandbuf deleteCharactersInRange: | | | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | case SDLK_RETURN: break; case SDLK_BACKSPACE: case SDLK_LEFT: if (commandbuf.length > 0) [commandbuf deleteCharactersInRange: OFMakeRange( commandbuf.length - 1, 1)]; resetcomplete(); break; case SDLK_UP: if (histpos) commandbuf = |
︙ | ︙ | |||
217 218 219 220 221 222 223 | default: resetcomplete(); } } else { if (code == SDLK_RETURN) { if (commandbuf.length > 0) { if (vhistory == nil) | | < | | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | default: resetcomplete(); } } else { if (code == SDLK_RETURN) { if (commandbuf.length > 0) { if (vhistory == nil) vhistory = [[OFMutableArray alloc] init]; if (vhistory.count == 0 || ![vhistory.lastObject isEqual: commandbuf]) { // cap this? [vhistory addObject: [commandbuf copy]]; |
︙ | ︙ |
Modified src/cube.h from [e6d07ee71e] to [966c5f23a3].
︙ | ︙ | |||
104 105 106 107 108 109 110 | #define SW(w, x, y) SWS(w, x, y, ssize) #define S(x, y) SW(world, x, y) // convenient lookup of a lowest mip cube #define SMALLEST_FACTOR 6 // determines number of mips there can be #define DEFAULT_FACTOR 8 #define LARGEST_FACTOR 11 // 10 is already insane #define SOLID(x) ((x)->type == SOLID) #define MINBORD 2 // 2 cubes from the edge of the world are always solid | | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #define SW(w, x, y) SWS(w, x, y, ssize) #define S(x, y) SW(world, x, y) // convenient lookup of a lowest mip cube #define SMALLEST_FACTOR 6 // determines number of mips there can be #define DEFAULT_FACTOR 8 #define LARGEST_FACTOR 11 // 10 is already insane #define SOLID(x) ((x)->type == SOLID) #define MINBORD 2 // 2 cubes from the edge of the world are always solid #define OUTBORD(x, y) \ ((x) < MINBORD || (y) < MINBORD || (x) >= ssize - MINBORD || \ (y) >= ssize - MINBORD) struct block { int x, y, xs, ys; }; enum { |
︙ | ︙ | |||
251 252 253 254 255 256 257 | // globals ooh naughty #ifdef __cplusplus extern "C" { #endif // map data, the mips are sequential 2D arrays in memory extern struct sqr *world, *wmip[]; | | | | | | | | | | | | | | | | | | | | | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 | // globals ooh naughty #ifdef __cplusplus extern "C" { #endif // map data, the mips are sequential 2D arrays in memory extern struct sqr *world, *wmip[]; extern struct header hdr; // current map header extern int sfactor, ssize; // ssize = 2^sfactor extern int cubicsize, mipsize; // cubicsize = ssize^2 // all the other clients (in multiplayer) extern OFMutableArray *players; extern bool editmode; extern OFMutableArray<Entity *> *ents; // map entities extern OFVector3D worldpos; // current target of the crosshair in the world extern int lastmillis; // last time extern int curtime; // current frame time extern int gamemode, nextmode; extern int xtraverts; extern bool demoplayback; #ifdef __cplusplus } #endif #define DMF 16.0f #define DAF 1.0f #define DVF 100.0f #define VIRTW 2400 // virtual screen size for text & HUD #define VIRTH 1800 #define FONTH 64 #define PIXELTAB (VIRTW / 12) #define PI (3.1415927f) #define PI2 (2 * PI) #define vreject(v, u, max) \ ((v).x > (u).x + (max) || (v).x < (u).x - (max) || \ (v).y > (u).y + (max) || (v).y < (u).y - (max)) #define vlinterp(v, f, u, g) \ { \ (v).x = (v).x * f + (u).x * g; \ (v).y = (v).y * f + (u).y * g; \ (v).z = (v).z * f + (u).z * g; \ } #define sgetstr() \ { \ char *t = text; \ do { \ *t = getint(&p); \ } while (*t++); \ } // used by networking #define m_noitems (gamemode >= 4) #define m_noitemsrail (gamemode <= 5) #define m_arena (gamemode >= 8) #define m_tarena (gamemode >= 10) #define m_teammode (gamemode & 1 && gamemode > 2) |
︙ | ︙ |
Modified src/editing.m from [1510ae8332] to [974268cfe4].
︙ | ︙ | |||
39 40 41 42 43 44 45 | } }); } int selh = 0; bool selset = false; | | | | | | | | | | | | | > | > | > | < > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | } }); } int selh = 0; bool selset = false; #define loopselxy(b) \ { \ makeundo(); \ for (int x = 0; x < sel->xs; x++) { \ for (int y = 0; y < sel->ys; y++) { \ struct sqr *s = S(sel->x + x, sel->y + y); \ b; \ } \ } \ remip(sel, 0); \ } int cx, cy, ch; int curedittex[] = { -1, -1, -1 }; bool dragging = false; int lastx, lasty, lasth; int lasttype = 0, lasttex = 0; static struct sqr rtex; VAR(editing, 0, 0, 1); void toggleedit() { Player *player1 = Player.player1; if (player1.state == CS_DEAD) // do not allow dead players to edit to avoid state return; if (!editmode && !allowedittoggle()) // not in most multiplayer modes return; if (!(editmode = !editmode)) { // reset triggers to allow quick playtesting settagareas(); // find spawn closest to current floating pos entinmap(player1); } else { // clear trigger areas to allow them to be edited resettagareas(); player1.health = 100; if (m_classicsp) // all monsters back at their spawns for editing [Monster resetAll]; projreset(); } Cube.sharedInstance.repeatsKeys = editmode; |
︙ | ︙ | |||
123 124 125 126 127 128 129 | noselection() { if (!selset) conoutf(@"no selection"); return !selset; } | | | | | | | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | noselection() { if (!selset) conoutf(@"no selection"); return !selset; } #define EDITSEL \ if (noteditmode() || noselection()) \ return; #define EDITSELMP \ if (noteditmode() || noselection() || multiplayer()) \ return; #define EDITMP \ if (noteditmode() || multiplayer()) \ return; COMMAND(select, ARG_4INT, (^ (int x, int y, int xs, int ys) { struct block s = { x, y, xs, ys }; sel = s; selh = 0; correctsel(); |
︙ | ︙ | |||
338 339 340 341 342 343 344 345 | } makeundo(); copybuf->x = sel.x; copybuf->y = sel.y; blockpaste(copybuf); }) void | > | < | 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | } makeundo(); copybuf->x = sel.x; copybuf->y = sel.y; blockpaste(copybuf); }) // maintain most recently used of the texture lists when applying texture void tofronttex() { for (int i = 0; i < 3; i++) { int c = curedittex[i]; if (c >= 0) { unsigned char *p = hdr.texlists[i]; int t = p[c]; for (int a = c - 1; a >= 0; a--) |
︙ | ︙ | |||
404 405 406 407 408 409 410 | COMMAND(editheight, ARG_2INT, ^ (int flr, int amount) { editheight(flr, amount); }) void edittexxy(int type, int t, const struct block *sel) { | | > | | | | | | | | | | | | > | | 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | COMMAND(editheight, ARG_2INT, ^ (int flr, int amount) { editheight(flr, amount); }) void edittexxy(int type, int t, const struct block *sel) { loopselxy( switch (type) { case 0: s->ftex = t; break; case 1: s->wtex = t; break; case 2: s->ctex = t; break; case 3: s->utex = t; break; } ); } COMMAND(edittex, ARG_2INT, ^ (int type, int dir) { EDITSEL; if (type < 0 || type > 3) return; |
︙ | ︙ | |||
482 483 484 485 486 487 488 | } static void edittype(int type) { EDITSEL; | < | | | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | } static void edittype(int type) { EDITSEL; if (type == CORNER && (sel.xs != sel.ys || sel.xs == 3 || (sel.xs > 4 && sel.xs != 8) || sel.x & ~-sel.xs || sel.y & ~-sel.ys)) { conoutf(@"corner selection must be power of 2 aligned"); return; } edittypexy(type, &sel); addmsg(1, 6, SV_EDITS, sel.x, sel.y, sel.xs, sel.ys, type); } |
︙ | ︙ | |||
578 579 580 581 582 583 584 | sel.xs = MAXARCHVERT; if (sel.ys > MAXARCHVERT) sel.ys = MAXARCHVERT; struct block *sel_ = &sel; // Ugly hack to make the macro work. struct block *sel = sel_; | | < | | | | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | sel.xs = MAXARCHVERT; if (sel.ys > MAXARCHVERT) sel.ys = MAXARCHVERT; struct block *sel_ = &sel; // Ugly hack to make the macro work. struct block *sel = sel_; loopselxy(s->vdelta = sel->xs > sel->ys ? (archverts[sel->xs - 1][x] + (y == 0 || y == sel->ys - 1 ? sidedelta : 0)) : (archverts[sel->ys - 1][y] + (x == 0 || x == sel->xs - 1 ? sidedelta : 0))); remipmore(sel, 0); }) COMMAND(slope, ARG_2INT, ^ (int xd, int yd) { EDITSELMP; int off = 0; |
︙ | ︙ |
Modified src/entities.m from [945da2b6da] to [384373114a].
︙ | ︙ | |||
47 48 49 50 51 52 53 | for (Entity *e in ents) { if (e.type == MAPMODEL) { MapModelInfo *mmi = getmminfo(e.attr2); if (mmi == nil) continue; rendermodel(mmi.name, 0, 1, e.attr4, (float)mmi.rad, | | | < | | < | < | > | < | < < | < | | < | | | | | < | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | for (Entity *e in ents) { if (e.type == MAPMODEL) { MapModelInfo *mmi = getmminfo(e.attr2); if (mmi == nil) continue; rendermodel(mmi.name, 0, 1, e.attr4, (float)mmi.rad, OFMakeVector3D(e.x, (float)S(e.x, e.y)->floor + mmi.zoff + e.attr3, e.y), (float)((e.attr1 + 7) - (e.attr1 + 7) % 15), 0, false, 1.0f, 10.0f, mmi.snap, 0); } else { if (OUTBORD(e.x, e.y)) continue; if (e.type != CARROT) { if (!e.spawned && e.type != TELEPORT) continue; if (e.type < I_SHELLS || e.type > TELEPORT) continue; renderent(e, entmdlnames[e.type - I_SHELLS], (float)(1 + sin(lastmillis / 100.0 + e.x + e.y) / 20), lastmillis / 10.0f, 0, 1, 0, 10.0f); } else { switch (e.attr2) { case 1: case 3: continue; case 2: case 0: if (!e.spawned) continue; renderent(e, @"carrot", (float)(1 + sin(lastmillis / 100.0 + e.x + e.y) / 20), lastmillis / (e.attr2 ? 1.0f : 10.0f), 0, 1, 0, 10.0f); break; case 4: renderent(e, @"switch2", 3, (float)e.attr3 * 90, (!e.spawned && !triggertime) ? 1 : 0, (e.spawned || !triggertime) ? 1 : 2, triggertime, 1050.0f); break; case 5: renderent(e, @"switch1", -0.15f, (float)e.attr3 * 90, (!e.spawned && !triggertime) ? 30 : 0, (e.spawned || !triggertime) ? 1 : 30, triggertime, 35.0f); break; } } } } } |
︙ | ︙ |
Modified src/physics.m from [95d4c13f64] to [775d6c79ad].
︙ | ︙ | |||
11 12 13 14 15 16 17 | #import "MapModelInfo.h" #import "Monster.h" #import "Player.h" #import "Variable.h" // collide with player or monster static bool | < | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #import "MapModelInfo.h" #import "Monster.h" #import "Player.h" #import "Variable.h" // collide with player or monster static bool plcollide(DynamicEntity *d, DynamicEntity *o, float *headspace, float *hi, float *lo) { if (o.state != CS_ALIVE) return true; const float r = o.radius + d.radius; if (fabs(o.origin.x - d.origin.x) < r && fabs(o.origin.y - d.origin.y) < r) { |
︙ | ︙ | |||
121 122 123 124 125 126 127 | float floor = s->floor; switch (s->type) { case SOLID: return false; case CORNER: { int bx = x, by = y, bs = 1; | | < | < | < | | < < | | < < | | | | < | | < | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | float floor = s->floor; switch (s->type) { case SOLID: return false; case CORNER: { int bx = x, by = y, bs = 1; if ((x == x1 && y == y1 && cornertest(0, x, y, -1, -1, &bx, &by, &bs) && fx1 - bx + fy1 - by <= bs) || (x == x2 && y == y1 && cornertest(0, x, y, 1, -1, &bx, &by, &bs) && fx2 - bx >= fy1 - by) || (x == x1 && y == y2 && cornertest(0, x, y, -1, 1, &bx, &by, &bs) && fx1 - bx <= fy2 - by) || (x == x2 && y == y2 && cornertest(0, x, y, 1, 1, &bx, &by, &bs) && fx2 - bx + fy2 - by >= bs)) return false; break; } // FIXME: too simplistic collision with slopes, makes // it feels like tiny stairs case FHF: floor -= (s->vdelta + S(x + 1, y)->vdelta + S(x, y + 1)->vdelta + S(x + 1, y + 1)->vdelta) / 16.0f; break; case CHF: ceil += (s->vdelta + S(x + 1, y)->vdelta + S(x, y + 1)->vdelta + S(x + 1, y + 1)->vdelta) / 16.0f; } if (ceil < hi) hi = ceil; if (floor > lo) lo = floor; if (floor < minfloor) |
︙ | ︙ | |||
210 211 212 213 214 215 216 | // rise thru stair d.origin = OFAddVectors3D( d.origin, OFMakeVector3D(0, 0, rise)); else return false; } else // gravity | | < | | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | // rise thru stair d.origin = OFAddVectors3D( d.origin, OFMakeVector3D(0, 0, rise)); else return false; } else // gravity d.origin = OFSubtractVectors3D(d.origin, OFMakeVector3D( 0, 0, min(min(drop, space), headspace))); const float space2 = hi - (d.origin.z + d.aboveEye); if (space2 < 0) { if (space2 < -0.1) return false; // hack alert! // glue to ceiling d.origin = OFMakeVector3D( |
︙ | ︙ | |||
403 404 405 406 407 408 409 | // mostly if (pl.origin.x < 0 || pl.origin.x >= ssize || pl.origin.y < 0 || pl.origin.y > ssize) pl.outsideMap = true; else { struct sqr *s = S((int)pl.origin.x, (int)pl.origin.y); | | < | | | | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | // mostly if (pl.origin.x < 0 || pl.origin.x >= ssize || pl.origin.y < 0 || pl.origin.y > ssize) pl.outsideMap = true; else { struct sqr *s = S((int)pl.origin.x, (int)pl.origin.y); pl.outsideMap = (SOLID(s) || pl.origin.z < s->floor - (s->type == FHF ? s->vdelta / 4 : 0) || pl.origin.z > s->ceil + (s->type == CHF ? s->vdelta / 4 : 0)); } // automatically apply smooth roll when strafing if (pl.strafe == 0) pl.roll = pl.roll / (1 + (float)sqrt((float)curtime) / 25); else { |
︙ | ︙ | |||
439 440 441 442 443 444 445 | pl.inWater = water; } void moveplayer(DynamicEntity *pl, int moveres, bool local) { for (int i = 0; i < physicsrepeat; i++) | | < < | | 428 429 430 431 432 433 434 435 436 437 | pl.inWater = water; } void moveplayer(DynamicEntity *pl, int moveres, bool local) { for (int i = 0; i < physicsrepeat; i++) moveplayer4(pl, moveres, local, i ? curtime / physicsrepeat : curtime - curtime / physicsrepeat * (physicsrepeat - 1)); } |
Modified src/rendercubes.m from [d20e5d1984] to [ee90f3d4f5].
︙ | ︙ | |||
27 28 29 30 31 32 33 | setarraypointers(); } // generating the actual vertices is done dynamically every frame and sits at // the leaves of all these functions, and are part of the cpu bottleneck on // really slow machines, hence the macros. | | | | | | | | | | | | | | | | | | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | setarraypointers(); } // generating the actual vertices is done dynamically every frame and sits at // the leaves of all these functions, and are part of the cpu bottleneck on // really slow machines, hence the macros. #define vertcheck() \ { \ if (curvert >= curmaxverts) \ reallocv(); \ } #define vertf(v1, v2, v3, ls, t1, t2) \ { \ struct vertex *v = &verts[curvert++]; \ v->u = t1; \ v->v = t2; \ v->x = v1; \ v->y = v2; \ v->z = v3; \ v->r = ls->r; \ v->g = ls->g; \ v->b = ls->b; \ v->a = 255; \ } #define vert(v1, v2, v3, ls, t1, t2) \ { \ vertf((float)(v1), (float)(v2), (float)(v3), ls, t1, t2); \ } int nquads; const float TEXTURESCALE = 32.0f; bool floorstrip = false, deltastrip = false; int oh, oy, ox, ogltex; // the o* vars are used by the stripification |
︙ | ︙ | |||
71 72 73 74 75 76 77 | void mipstats(int a, int b, int c) { if (showm) conoutf(@"1x1/2x2/4x4: %d / %d / %d", a, b, c); } | | | | | | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | void mipstats(int a, int b, int c) { if (showm) conoutf(@"1x1/2x2/4x4: %d / %d / %d", a, b, c); } #define stripend() \ { \ if (floorstrip || deltastrip) { \ addstrip(ogltex, firstindex, curvert - firstindex); \ floorstrip = deltastrip = false; \ } \ } void finishstrips() { stripend(); } |
︙ | ︙ | |||
134 135 136 137 138 139 140 141 | ol3b = l1->b; ol4r = l2->r; ol4g = l2->g; ol4b = l2->b; } else // continue strip { int lighterr = lighterror * 2; if ((abs(ol3r - l3->r) < lighterr && | > | < | | | | < | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | ol3b = l1->b; ol4r = l2->r; ol4g = l2->g; ol4b = l2->b; } else // continue strip { int lighterr = lighterror * 2; // skip vertices if light values are close enough if ((abs(ol3r - l3->r) < lighterr && abs(ol4r - l4->r) < lighterr && abs(ol3g - l3->g) < lighterr && abs(ol4g - l4->g) < lighterr && abs(ol3b - l3->b) < lighterr && abs(ol4b - l4->b) < lighterr) || !wtex) { curvert -= 2; nquads--; } else { unsigned char *p3 = (unsigned char *)(&verts[curvert - 1].r); ol3r = p3[0]; ol3g = p3[1]; |
︙ | ︙ |
Modified src/renderextras.m from [f1478ac26e] to [8a14c68979].
︙ | ︙ | |||
202 203 204 205 206 207 208 | particle_splash(2, 2, 40, OFMakeVector3D(e.x, e.y, e.z)); } int e = closestent(); if (e >= 0) { Entity *c = ents[e]; | < | | | | | | | 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | particle_splash(2, 2, 40, OFMakeVector3D(e.x, e.y, e.z)); } int e = closestent(); if (e >= 0) { Entity *c = ents[e]; closeent = [OFString stringWithFormat: @"closest entity = %@ (%d, %d, %d, %d), " @"selection = (%d, %d)", entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, getvar(@"selxs"), getvar(@"selys")]; } } COMMAND(loadsky, ARG_1STR, (^ (OFString *basename) { static OFString *lastsky = @""; basename = [basename stringByReplacingOccurrencesOfString: @"\\" withString: @"/"]; if ([lastsky isEqual: basename]) return; static const OFString *side[] = { @"ft", @"bk", @"lf", @"rt", @"dn", @"up" }; int texnum = 14; |
︙ | ︙ |
Modified src/rendergl.m from [8875dffa42] to [e10c3367c9].
︙ | ︙ | |||
54 55 56 57 58 59 60 | char *exts = (char *)glGetString(GL_EXTENSIONS); if (strstr(exts, "GL_EXT_texture_env_combine")) hasoverbright = true; else conoutf(@"WARNING: cannot use overbright lighting, using old " | | | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | char *exts = (char *)glGetString(GL_EXTENSIONS); if (strstr(exts, "GL_EXT_texture_env_combine")) hasoverbright = true; else conoutf(@"WARNING: cannot use overbright lighting, using old " @"lighting model!"); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glmaxtexsize); purgetextures(); if (!(qsphere = gluNewQuadric())) fatal(@"glu sphere"); |
︙ | ︙ | |||
100 101 102 103 104 105 106 | } @try { SDL_Surface *converted = SDL_ConvertSurface(s, format, 0); if (converted == NULL) { conoutf(@"texture cannot be converted " | | < | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | } @try { SDL_Surface *converted = SDL_ConvertSurface(s, format, 0); if (converted == NULL) { conoutf(@"texture cannot be converted " @"to 24bpp: %@", IRI.string); return false; } SDL_FreeSurface(s); s = converted; } @finally { SDL_FreeFormat(format); |
︙ | ︙ | |||
147 148 149 150 151 152 153 | IRI.string); // for voodoo cards under linux scaledimg = OFAllocMemory(1, *xs * *ys * 3); gluScaleImage(GL_RGB, s->w, s->h, GL_UNSIGNED_BYTE, s->pixels, *xs, *ys, GL_UNSIGNED_BYTE, scaledimg); } if (gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, *xs, *ys, GL_RGB, | | | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | IRI.string); // for voodoo cards under linux scaledimg = OFAllocMemory(1, *xs * *ys * 3); gluScaleImage(GL_RGB, s->w, s->h, GL_UNSIGNED_BYTE, s->pixels, *xs, *ys, GL_UNSIGNED_BYTE, scaledimg); } if (gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, *xs, *ys, GL_RGB, GL_UNSIGNED_BYTE, scaledimg)) fatal(@"could not build mipmaps"); if (*xs != s->w) free(scaledimg); SDL_FreeSurface(s); |
︙ | ︙ | |||
198 199 200 201 202 203 204 | int num = curtexnum++, frame = aframe.cube_intValue; if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES) return; mapping[num][frame] = 1; mapname[num][frame] = [name stringByReplacingOccurrencesOfString: @"\\" | | | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | int num = curtexnum++, frame = aframe.cube_intValue; if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES) return; mapping[num][frame] = 1; mapname[num][frame] = [name stringByReplacingOccurrencesOfString: @"\\" withString: @"/"]; })) int lookuptexture(int tex, int *xs, int *ys) { int frame = 0; // other frames? int tid = mapping[tex][frame]; |
︙ | ︙ | |||
330 331 332 333 334 335 336 | VARFP(gamma, 30, 100, 300, { float f = gamma / 100.0f; Uint16 ramp[256]; SDL_CalculateGammaRamp(f, ramp); | | | | < | < | > | 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | VARFP(gamma, 30, 100, 300, { float f = gamma / 100.0f; Uint16 ramp[256]; SDL_CalculateGammaRamp(f, ramp); if (SDL_SetWindowGammaRamp(Cube.sharedInstance.window, ramp, ramp, ramp) == -1) { conoutf( @"Could not set gamma (card/driver doesn't support it?)"); conoutf(@"sdl: %s", SDL_GetError()); } }) void transplayer() { Player *player1 = Player.player1; glLoadIdentity(); glRotated(player1.roll, 0.0, 0.0, 1.0); glRotated(player1.pitch, -1.0, 0.0, 0.0); glRotated(player1.yaw, 0.0, 1.0, 0.0); glTranslated(-player1.origin.x, (player1.state == CS_DEAD ? player1.eyeHeight - 0.2f : 0) - player1.origin.z, -player1.origin.y); } VARP(fov, 10, 105, 120); int xtraverts; VAR(fog, 64, 180, 1024); VAR(fogcolour, 0, 0x8099B3, 0xFFFFFF); VARP(hudgun, 0, 1, 1); OFString *hudgunnames[] = { @"hudguns/fist", @"hudguns/shotg", @"hudguns/chaing", @"hudguns/rocket", @"hudguns/rifle" }; void drawhudmodel(int start, int end, float speed, int base) { Player *player1 = Player.player1; rendermodel(hudgunnames[player1.gunSelect], start, end, 0, 1.0f, OFMakeVector3D(player1.origin.x, player1.origin.z, player1.origin.y), player1.yaw + 90, player1.pitch, false, 1.0f, speed, 0, base); } void drawhudgun(float fovy, float aspect, int farplane) { Player *player1 = Player.player1; |
︙ | ︙ |
Modified src/rendermd2.m from [923fa1d88f] to [11936c1b8d].
︙ | ︙ | |||
87 88 89 90 91 92 93 | rendermodel(OFString *mdl, int frame, int range, int tex, float rad, OFVector3D position, float yaw, float pitch, bool teammate, float scale, float speed, int snap, int basetime) { MD2 *m = loadmodel(mdl); if (isoccluded(Player.player1.origin.x, Player.player1.origin.y, | | | | | | | | | | | | | | | | | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | rendermodel(OFString *mdl, int frame, int range, int tex, float rad, OFVector3D position, float yaw, float pitch, bool teammate, float scale, float speed, int snap, int basetime) { MD2 *m = loadmodel(mdl); if (isoccluded(Player.player1.origin.x, Player.player1.origin.y, position.x - rad, position.z - rad, rad * 2)) return; delayedload(m); int xs, ys; glBindTexture(GL_TEXTURE_2D, tex ? lookuptexture(tex, &xs, &ys) : FIRSTMDL + m.mdlnum); int ix = (int)position.x; int iy = (int)position.z; OFColor *light = OFColor.white; if (!OUTBORD(ix, iy)) { struct sqr *s = S(ix, iy); float ll = 256.0f; // 0.96f; float of = 0.0f; // 0.1f; light = [OFColor colorWithRed: s->r / ll + of green: s->g / ll + of blue: s->b / ll + of alpha: 1.0f]; } if (teammate) { float red, green, blue; [light getRed: &red green: &green blue: &blue alpha: NULL]; light = [OFColor colorWithRed: red * 0.6f green: green * 0.7f blue: blue * 1.2f alpha: 1.0f]; } [m renderWithLight: light frame: frame range: range position: position yaw: yaw pitch: pitch scale: scale speed: speed snap: snap basetime: basetime]; } |
Modified src/renderparticles.m from [f1b52c549a] to [187397123f].
︙ | ︙ | |||
68 69 70 71 72 73 74 | struct parttype { float r, g, b; int gr, tex; float sz; } parttypes[] = { { 0.7f, 0.6f, 0.3f, 2, 3, 0.06f }, // yellow: sparks { 0.5f, 0.5f, 0.5f, 20, 7, 0.15f }, // grey: small smoke | | < | | | | | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | struct parttype { float r, g, b; int gr, tex; float sz; } parttypes[] = { { 0.7f, 0.6f, 0.3f, 2, 3, 0.06f }, // yellow: sparks { 0.5f, 0.5f, 0.5f, 20, 7, 0.15f }, // grey: small smoke { 0.2f, 0.2f, 1.0f, 20, 3, 0.08f }, // blue: edit mode entities { 1.0f, 0.1f, 0.1f, 1, 7, 0.06f }, // red: blood spats { 1.0f, 0.8f, 0.8f, 20, 6, 1.2f }, // yellow: fireball1 { 0.5f, 0.5f, 0.5f, 20, 7, 0.6f }, // grey: big smoke { 1.0f, 1.0f, 1.0f, 20, 8, 1.2f }, // blue: fireball2 { 1.0f, 1.0f, 1.0f, 20, 9, 1.2f }, // green: fireball3 { 1.0f, 0.1f, 0.1f, 0, 7, 0.2f }, // red: demotrack }; int numrender = 0; for (struct particle *p, **pp = &parlist; (p = *pp) != NULL;) { struct parttype *pt = &parttypes[p->type]; |
︙ | ︙ |
Modified src/rendertext.m from [656fe9791c] to [af0dd28de8].
︙ | ︙ | |||
136 137 138 139 140 141 142 | void draw_textf(OFConstantString *format, int left, int top, int gl_num, ...) { va_list arguments; va_start(arguments, gl_num); OFString *str = [[OFString alloc] initWithFormat: format | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | void draw_textf(OFConstantString *format, int left, int top, int gl_num, ...) { va_list arguments; va_start(arguments, gl_num); OFString *str = [[OFString alloc] initWithFormat: format arguments: arguments]; va_end(arguments); draw_text(str, left, top, gl_num); } void draw_text(OFString *string, int left, int top, int gl_num) { |
︙ | ︙ |
Modified src/rndmap.m from [050a1e4f8d] to [b1dc1f80ec].
︙ | ︙ | |||
12 13 14 15 16 17 18 | ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f; } float smoothednoise(int x, int y, int seed) { | < | | < | < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f; } float smoothednoise(int x, int y, int seed) { float corners = (noise(x - 1, y - 1, seed) + noise(x + 1, y - 1, seed) + noise(x - 1, y + 1, seed) + noise(x + 1, y + 1, seed)) / 16; float sides = (noise(x - 1, y, seed) + noise(x + 1, y, seed) + noise(x, y - 1, seed) + noise(x, y + 1, seed)) / 8; float center = noise(x, y, seed) / 4; return corners + sides + center; } float interpolate(float a, float b, float x) { |
︙ | ︙ | |||
74 75 76 77 78 79 80 | if (!scale) scale = 10; for (int x = b->x; x <= b->x + b->xs; x++) { for (int y = b->y; y <= b->y + b->ys; y++) { struct sqr *s = S(x, y); if (!SOLID(s) && x != b->x + b->xs && y != b->y + b->ys) s->type = FHF; | | | | < < | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | if (!scale) scale = 10; for (int x = b->x; x <= b->x + b->xs; x++) { for (int y = b->y; y <= b->y + b->ys; y++) { struct sqr *s = S(x, y); if (!SOLID(s) && x != b->x + b->xs && y != b->y + b->ys) s->type = FHF; s->vdelta = (int)(perlinnoise_2D( x / ((float)scale) + seed, y / ((float)scale) + seed, 1000, 0.01f) * 50 + 25); if (s->vdelta > 128) s->vdelta = 0; } } } |
Modified src/savegamedemo.m from [94bda1495e] to [09c2cc3e3c].
︙ | ︙ | |||
160 161 162 163 164 165 166 | char mapname[_MAXDEFSTR] = { 0 }; char buf[8]; gzread(f, buf, 8); if (strncmp(buf, "CUBESAVE", 8)) goto out; if (gzgetc(f) != islittleendian) | | | | | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | char mapname[_MAXDEFSTR] = { 0 }; char buf[8]; gzread(f, buf, 8); if (strncmp(buf, "CUBESAVE", 8)) goto out; if (gzgetc(f) != islittleendian) // not supporting save->load accross incompatible architectures // simpifies things a LOT goto out; if (gzgeti() != SAVEGAMEVERSION || gzgeti() != DynamicEntity.serializedSize) goto out; gzread(f, mapname, _MAXDEFSTR); nextmode = gzgeti(); // continue below once map has been loaded and client & server // have updated changemap(@(mapname)); return; out: conoutf(@"aborting: savegame/demo from a different version of " @"cube or cpu architecture"); stop(); } COMMAND(loadgame, ARG_1STR, (^ (OFString *name) { OFString *path = [OFString stringWithFormat: @"savegames/%@.csgz", name]; OFIRI *IRI = [Cube.sharedInstance.userDataIRI IRIByAppendingPathComponent: path]; loadstate(IRI); })) void loadgameout() { stop(); conoutf(@"loadgame incomplete: savegame from a different version of " @"this map"); } void loadgamerest() { if (demoplayback || !f) return; |
︙ | ︙ | |||
377 378 379 380 381 382 383 | setclient(democlientnum, [Player.player1 copy]); readdemotime(); } VAR(demodelaymsec, 0, 120, 500); // spline interpolation | | | | | | | | | | | | | | | | | | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | setclient(democlientnum, [Player.player1 copy]); readdemotime(); } VAR(demodelaymsec, 0, 120, 500); // spline interpolation #define catmulrom(z, a, b, c, s, dest) \ { \ OFVector3D t1 = OFSubtractVectors3D(b, z); \ t1 = OFMultiplyVector3D(t1, 0.5f); \ \ OFVector3D t2 = OFSubtractVectors3D(c, a); \ t2 = OFMultiplyVector3D(t2, 0.5f); \ \ float s2 = s * s; \ float s3 = s * s2; \ \ dest = OFMultiplyVector3D(a, 2 * s3 - 3 * s2 + 1); \ OFVector3D t = OFMultiplyVector3D(b, -2 * s3 + 3 * s2); \ dest = OFAddVectors3D(dest, t); \ t1 = OFMultiplyVector3D(t1, s3 - 2 * s2 + s); \ dest = OFAddVectors3D(dest, t1); \ t2 = OFMultiplyVector3D(t2, s3 - s2); \ dest = OFAddVectors3D(dest, t2); \ } void fixwrap(DynamicEntity *a, DynamicEntity *b) { while (b.yaw - a.yaw > 180) a.yaw += 360; |
︙ | ︙ | |||
449 450 451 452 453 454 455 | gzgetv(&dorig); particle_splash(3, ddamage, 1000, dorig); } // FIXME: set more client state here } // insert latest copy of player into history | < | | | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | gzgetv(&dorig); particle_splash(3, ddamage, 1000, dorig); } // FIXME: set more client state here } // insert latest copy of player into history if (extras && (playerhistory.count == 0 || playerhistory.lastObject.lastUpdate != playbacktime)) { Player *d = [target copy]; d.lastUpdate = playbacktime; if (playerhistory == nil) playerhistory = [[OFMutableArray alloc] init]; [playerhistory addObject: d]; |
︙ | ︙ |
Modified src/server.m from [95faadaf28] to [043bbacb23].
︙ | ︙ | |||
395 396 397 398 399 400 401 402 | mapend = lastsec + minremain * 60; interm = 0; } int nonlocalclients = 0; int lastconnect = 0; void | > > | < < | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | mapend = lastsec + minremain * 60; interm = 0; } int nonlocalclients = 0; int lastconnect = 0; // main server update, called from cube main loop in sp, or dedicated server // loop void serverslice(int seconds, unsigned int timeout) { // spawn entities when timer reached [sents enumerateObjectsUsingBlock: ^ (ServerEntity *e, size_t i, bool *stop) { if (e.spawnsecs && (e.spawnsecs -= seconds - lastsec) <= 0) { e.spawnsecs = 0; e.spawned = true; |
︙ | ︙ | |||
468 469 470 471 472 473 474 | case ENET_EVENT_TYPE_CONNECT: { Client *c = addclient(); c.type = ST_TCPIP; c.peer = event.peer; c.peer->data = (void *)(clients.count - 1); char hn[1024]; c.hostname = (enet_address_get_host( | | < | | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | case ENET_EVENT_TYPE_CONNECT: { Client *c = addclient(); c.type = ST_TCPIP; c.peer = event.peer; c.peer->data = (void *)(clients.count - 1); char hn[1024]; c.hostname = (enet_address_get_host( &c.peer->address, hn, sizeof(hn)) == 0 ? @(hn) : @"localhost"); [OFStdOut writeFormat: @"client connected (%@)\n", c.hostname]; send_welcome(lastconnect = clients.count - 1); break; } case ENET_EVENT_TYPE_RECEIVE: brec += event.packet->dataLength; |
︙ | ︙ |
Modified src/sound.m from [78a898d2ad] to [16682ac683].
︙ | ︙ | |||
53 54 55 56 57 58 59 | if (nosound) return; stopsound(); if (soundvol && musicvol) { name = [name stringByReplacingOccurrencesOfString: @"\\" | | | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | if (nosound) return; stopsound(); if (soundvol && musicvol) { name = [name stringByReplacingOccurrencesOfString: @"\\" withString: @"/"]; OFString *path = [OFString stringWithFormat: @"packages/%@", name]; OFIRI *IRI = [Cube.sharedInstance.gameDataIRI IRIByAppendingPathComponent: path]; if ((mod = Mix_LoadMUS( IRI.fileSystemRepresentation.UTF8String)) != NULL) { Mix_PlayMusic(mod, -1); Mix_VolumeMusic((musicvol * MAXVOL) / 255); } } })) static OFMutableData *samples; |
︙ | ︙ |
Modified src/tools.h from [754911f423] to [d97579a315].
︙ | ︙ | |||
14 15 16 17 18 19 20 | #import <ObjFW/ObjFW.h> #define max(a, b) (((a) > (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b)) #define rnd(max) (rand() % (max)) #define rndreset() (srand(1)) | | | | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #import <ObjFW/ObjFW.h> #define max(a, b) (((a) > (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b)) #define rnd(max) (rand() % (max)) #define rndreset() (srand(1)) #define rndtime() \ { \ for (int i = 0; i < (lastmillis & 0xF); i++) \ rnd(i + 1); \ } #ifndef OF_WINDOWS # define __cdecl #endif #ifdef __cplusplus |
︙ | ︙ |
Modified src/world.m from [a8feb3f63c] to [555501440d].
︙ | ︙ | |||
157 158 159 160 161 162 163 | // crap hack, // needed for // rendering // large mips // next to hfs fh -= o[i]->vdelta / | | < | < | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | // crap hack, // needed for // rendering // large mips // next to hfs fh -= o[i]->vdelta / 4 + 2; if (o[i]->type == CHF) // FIXME: needs // to somehow // take into // account // middle // vertices on // higher mips ch += o[i]->vdelta / 4 + 2; } if (fh < floor) // take lowest floor and // highest ceil, so we // never have to see // missing lower/upper // from the side |
︙ | ︙ | |||
210 211 212 213 214 215 216 | // exactly equal if (o[i]->type != o[3]->type || o[i]->floor != o[3]->floor || o[i]->ceil != o[3]->ceil || o[i]->ftex != o[3]->ftex || o[i]->ctex != o[3]->ctex || abs(o[i + 1]->r - o[0]->r) > | | | | | | < | | < | | < | | < | | < | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | // exactly equal if (o[i]->type != o[3]->type || o[i]->floor != o[3]->floor || o[i]->ceil != o[3]->ceil || o[i]->ftex != o[3]->ftex || o[i]->ctex != o[3]->ctex || abs(o[i + 1]->r - o[0]->r) > lighterr || abs(o[i + 1]->g - o[0]->g) > lighterr || abs(o[i + 1]->b - o[0]->b) > lighterr || o[i]->utex != o[3]->utex || o[i]->wtex != o[3]->wtex) goto c; } // can make a perfect mip out of a hf if slopes // lie on one line if (r->type == CHF || r->type == FHF) { if (o[0]->vdelta - o[1]->vdelta != o[1]->vdelta - SWS(w, x + 2, y, ws)->vdelta || o[0]->vdelta - o[2]->vdelta != o[2]->vdelta - SWS(w, x + 2, y + 2, ws)->vdelta || o[0]->vdelta - o[3]->vdelta != o[3]->vdelta - SWS(w, x, y + 2, ws)->vdelta || o[3]->vdelta - o[2]->vdelta != o[2]->vdelta - SWS(w, x + 2, y + 1, ws)->vdelta || o[1]->vdelta - o[2]->vdelta != o[2]->vdelta - SWS(w, x + 1, y + 2, ws)->vdelta) goto c; } } { // if any of the constituents is not perfect, // then this one isn't either for (int i = 0; i < 4; i++) |
︙ | ︙ |
Modified src/worldio.m from [f35a650122] to [3c6f02e0b1].
︙ | ︙ | |||
166 167 168 169 170 171 172 | // run-length encoding and leaves out data for certain kinds of cubes, then zlib // removes the last bits of redundancy. Both passes contribute greatly to the // miniscule map sizes. void save_world(OFString *mname) { | | | | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | // run-length encoding and leaves out data for certain kinds of cubes, then zlib // removes the last bits of redundancy. Both passes contribute greatly to the // miniscule map sizes. void save_world(OFString *mname) { // wouldn't be able to reproduce tagged areas otherwise resettagareas(); voptimize(); toptimize(); if (mname.length == 0) mname = getclientmap(); setnames(mname); backup(cgzname, bakname); gzFile f = gzopen([cgzname cStringWithEncoding: OFLocale.encoding], |
︙ | ︙ | |||
199 200 201 202 203 204 205 | e.type, e.attr2, e.attr3, e.attr4 }; endianswap(&tmp, sizeof(short), 4); gzwrite(f, &tmp, sizeof(struct persistent_entity)); } } struct sqr *t = NULL; int sc = 0; | | | | | | | | | | | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | e.type, e.attr2, e.attr3, e.attr4 }; endianswap(&tmp, sizeof(short), 4); gzwrite(f, &tmp, sizeof(struct persistent_entity)); } } struct sqr *t = NULL; int sc = 0; #define spurge \ while (sc) { \ gzputc(f, 255); \ if (sc > 255) { \ gzputc(f, 255); \ sc -= 255; \ } else { \ gzputc(f, sc); \ sc = 0; \ } \ } for (int k = 0; k < cubicsize; k++) { struct sqr *s = &world[k]; #define c(f) (s->f == t->f) // 4 types of blocks, to compress a bit: // 255 (2): same as previous block + count // 254 (3): same as previous, except light // deprecated |
︙ | ︙ | |||
258 259 260 261 262 263 264 265 | settagareas(); } COMMAND(savemap, ARG_1STR, ^ (OFString *mname) { save_world(mname); }) void | > > | < | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | settagareas(); } COMMAND(savemap, ARG_1STR, ^ (OFString *mname) { save_world(mname); }) // still supports all map formats that have existed since the earliest cube // betas! void load_world(OFString *mname) { stopifrecording(); cleardlights(); pruneundos(0); setnames(mname); gzFile f = gzopen([cgzname cStringWithEncoding: OFLocale.encoding], "rb9"); |
︙ | ︙ |
Modified src/worldlight.m from [38a360a277] to [05ada5ded7].
︙ | ︙ | |||
38 39 40 41 42 43 44 | if (hasoverbright) { l /= lightscale; stepl /= lightscale; // coloured light version, special case because most lights are // white if (light.attr3 || light.attr4) { | | < | < < | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | if (hasoverbright) { l /= lightscale; stepl /= lightscale; // coloured light version, special case because most lights are // white if (light.attr3 || light.attr4) { int dimness = rnd((255 - (light.attr2 + light.attr3 + light.attr4) / 3) / 16 + 1); x += stepx * dimness; y += stepy * dimness; if (OUTBORD(x >> PRECBITS, y >> PRECBITS)) return; int g = light.attr3 << PRECBITS; |
︙ | ︙ | |||
144 145 146 147 148 149 150 | } // median filter, smooths out random noise in light and makes it more mipable void postlightarea(const struct block *a) { // assumes area not on edge of world | | > > | < | | | < > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | } // median filter, smooths out random noise in light and makes it more mipable void postlightarea(const struct block *a) { // assumes area not on edge of world for (int x = 0; x < a->xs; x++) { for (int y = 0; y < a->ys; y++) { struct sqr *s = S(x + a->x, y + a->y); // median is 4/2/1 instead #define median(m) \ s->m = (s->m * 2 + SW(s, 1, 0)->m * 2 + SW(s, 0, 1)->m * 2 + \ SW(s, -1, 0)->m * 2 + SW(s, 0, -1)->m * 2 + SW(s, 1, 1)->m + \ SW(s, 1, -1)->m + SW(s, -1, 1)->m + SW(s, -1, -1)->m) / 14; median(r); median(g); median(b); } } remip(a, 0); } void calclight() { |
︙ | ︙ |
Modified src/worldocull.m from [a7de71ad12] to [2e489013a3].
︙ | ︙ | |||
34 35 36 37 38 39 40 | float syaw = (player1.yaw - 90 - af) / 360 * PI2; for (int i = 0; i < NUMRAYS; i++) { float angle = i * PI2 / NUMRAYS; // try to avoid tracing ray if outside of frustrum // apitch must be bigger if fov > 120 if ((apitch > 45 || (angle < byaw && angle > syaw) || | | | > > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | float syaw = (player1.yaw - 90 - af) / 360 * PI2; for (int i = 0; i < NUMRAYS; i++) { float angle = i * PI2 / NUMRAYS; // try to avoid tracing ray if outside of frustrum // apitch must be bigger if fov > 120 if ((apitch > 45 || (angle < byaw && angle > syaw) || (angle < byaw - PI2 && angle > syaw - PI2) || (angle < byaw + PI2 && angle > syaw + PI2)) && !OUTBORD(vx, vy) && !SOLID(S((int)vx, (int)vy))) { float ray = i * 8 / (float)NUMRAYS; float dx, dy; if (ray > 1 && ray < 3) { dx = -(ray - 2); dy = 1; } else if (ray >= 3 && ray < 5) { dx = -1; dy = -(ray - 4); } else if (ray >= 5 && ray < 7) { dx = ray - 6; dy = -1; } else { dx = 1; dy = ray > 4 ? ray - 8 : ray; } float sx = vx; float sy = vy; for (;;) { sx += dx; sy += dy; // 90% of time spend in this function is on this // line |
︙ | ︙ | |||
121 122 123 124 125 126 127 | // find highest and lowest angle in the occlusion map that this cube // spans, based on its most left and right points on the border from the // viewer pov... I see no easier way to do this than this silly code // below float h, l; | | < > | < > | < > > < | > | < | | < > > > | | > | < < | > < | > | < > | < > > < | > < > > < > | < | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | // find highest and lowest angle in the occlusion map that this cube // spans, based on its most left and right points on the border from the // viewer pov... I see no easier way to do this than this silly code // below float h, l; if (cx <= vx) { // ABDFG if (cx + csize < vx) { // ADF if (cy <= vy) { // AD if (cy + csize < vy) { // A h = ca(-(cx - vx), -(cy + csize - vy)) + 4; l = ca(-(cx + csize - vx), -(cy - vy)) + 4; } else { // D h = ma(-(cx + csize - vx), -(cy + csize - vy)) + 4; l = ma(-(cx + csize - vx), -(cy - vy)) + 4; } } else { // F h = ca(cy + csize - vy, -(cx + csize - vx)) + 2; l = ca(cy - vy, -(cx - vx)) + 2; } } else { // BG if (cy <= vy) { if (cy + csize < vy) { // B h = ma(-(cy + csize - vy), cx - vx) + 6; l = ma(-(cy + csize - vy), cx + csize - vx) + 6; } else return 0; } else { // G h = ma(cy - vy, -(cx + csize - vx)) + 2; l = ma(cy - vy, -(cx - vx)) + 2; } } } else { // CEH if (cy <= vy) { // CE if (cy + csize < vy) { // C h = ca(-(cy - vy), cx - vx) + 6; l = ca(-(cy + csize - vy), cx + csize - vx) + 6; } else { // E h = ma(cx - vx, cy - vy); l = ma(cx - vx, cy + csize - vy); } } else { // H h = ca(cx + csize - vx, cy - vy); l = ca(cx - vx, cy + csize - vy); } } // get indexes into occlusion map from angles int si = h * (NUMRAYS / 8) + NUMRAYS; int ei = l * (NUMRAYS / 8) + NUMRAYS + 1; if (ei <= si) ei += NUMRAYS; for (int i = si; i <= ei; i++) if (dist < rdist[i & (NUMRAYS - 1)]) // if any value in this segment of the occlusion map is // further away then cube is not occluded return 0; return 1; // cube is entirely occluded } |
Modified src/worldrender.m from [60ed27f341] to [e1db597b95].
︙ | ︙ | |||
121 122 123 124 125 126 127 | render_seg_new( float vx, float vy, float vh, int mip, int x, int y, int xs, int ys) { struct sqr *w = wmip[mip]; int sz = ssize >> mip; int vxx = ((int)vx + (1 << mip) / 2) >> mip; int vyy = ((int)vy + (1 << mip) / 2) >> mip; | < | | > | | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | render_seg_new( float vx, float vy, float vh, int mip, int x, int y, int xs, int ys) { struct sqr *w = wmip[mip]; int sz = ssize >> mip; int vxx = ((int)vx + (1 << mip) / 2) >> mip; int vyy = ((int)vy + (1 << mip) / 2) >> mip; // these mark the rect inside the current rest that we want to render // using a lower mip level int lx = vxx - lodleft; int ly = vyy - lodtop; int rx = vxx + lodright; int ry = vyy + lodbot; float fsize = (float)(1 << mip); Player *player1 = Player.player1; for (int ox = x; ox < xs; ox++) { // first collect occlusion information for this block for (int oy = y; oy < ys; oy++) { SWS(w, ox, oy, sz)->occluded = isoccluded(player1.origin.x, player1.origin.y, (float)(ox << mip), (float)(oy << mip), fsize); } } int pvx = (int)vx >> mip; int pvy = (int)vy >> mip; if (pvx >= 0 && pvy >= 0 && pvx < sz && pvy < sz) { // SWS(w,vxx,vyy,sz)->occluded = 0; |
︙ | ︙ | |||
157 158 159 160 161 162 163 | // loop through the rect 3 times (for floor/ceil/walls seperately, to // facilitate dynamic stripify) for each we skip occluded cubes // (occlusion at higher mip levels is a big time saver!). during the // first loop (ceil) we collect cubes that lie within the lower mip rect // and are also deferred, and render them recursively. Anything left // (perfect mips and higher lods) we render here. | | | | | | | | | | | | | | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | // loop through the rect 3 times (for floor/ceil/walls seperately, to // facilitate dynamic stripify) for each we skip occluded cubes // (occlusion at higher mip levels is a big time saver!). during the // first loop (ceil) we collect cubes that lie within the lower mip rect // and are also deferred, and render them recursively. Anything left // (perfect mips and higher lods) we render here. #define LOOPH \ { \ for (int xx = x; xx < xs; xx++) \ for (int yy = y; yy < ys; yy++) { \ struct sqr *s = SWS(w, xx, yy, sz); \ if (s->occluded == 1) \ continue; \ if (s->defer && !s->occluded && mip && \ xx >= lx && xx < rx && yy >= ly && \ yy < ry) #define LOOPD \ struct sqr *t = SWS(s, 1, 0, sz); \ struct sqr *u = SWS(s, 1, 1, sz); \ struct sqr *v = SWS(s, 0, 1, sz); LOOPH // ceils { int start = yy; struct sqr *next; while (yy < ys - 1 && (next = SWS(w, xx, yy + 1, sz))->defer && |
︙ | ︙ |