Comment: | More style cleanup |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
753ff34122c906fdba43b8c382ac52cc |
User & Date: | js on 2025-03-08 03:05:16 |
Other Links: | manifest | tags |
2025-03-08
| ||
03:26 | Use ObjFW functions for memory management check-in: 71ebb79f8f user: js tags: trunk | |
03:05 | More style cleanup check-in: 753ff34122 user: js tags: trunk | |
02:38 | Improve clang-format check-in: 6f5dd50626 user: js tags: trunk | |
Modified src/.clang-format from [2a796d79cc] to [0d630f9489].
︙ | ︙ | |||
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 | AfterExternBlock: false BeforeCatch: false BeforeElse: false AlwaysBreakAfterReturnType: AllDefinitions AlignAfterOpenBracket: DontAlign AlignEscapedNewlines: Left AlignOperands: DontAlign ObjCBlockIndentWidth: 8 ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true ObjCPropertyAttributeOrder: [ class, direct, readonly, readwrite, nullable, nonnull, null_resettable, null_unspecified, assign, retain, strong, copy, weak, unsafe_unretained, atomic, nonatomic, getter, setter ] SpaceBeforeInheritanceColon: false QualifierAlignment: Left #RemoveEmptyLinesInUnwrappedLines: true RemoveSemicolon: true CompactNamespaces: true SortIncludes: CaseSensitive IndentPPDirectives: AfterHash PPIndentWidth: 1 | > > > | 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 | AfterExternBlock: false BeforeCatch: false BeforeElse: false AlwaysBreakAfterReturnType: AllDefinitions AlignAfterOpenBracket: DontAlign AlignEscapedNewlines: Left AlignOperands: DontAlign Cpp11BracedListStyle: false SpaceBeforeCpp11BracedList: true ObjCBlockIndentWidth: 8 ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true ObjCPropertyAttributeOrder: [ class, direct, readonly, readwrite, nullable, nonnull, null_resettable, null_unspecified, assign, retain, strong, copy, weak, unsafe_unretained, atomic, nonatomic, getter, setter ] SpaceBeforeInheritanceColon: false QualifierAlignment: Left MaxEmptyLinesToKeep: 1 #RemoveEmptyLinesInUnwrappedLines: true RemoveSemicolon: true CompactNamespaces: true SortIncludes: CaseSensitive IndentPPDirectives: AfterHash PPIndentWidth: 1 |
Modified src/Cube.mm from [00b4da043c] to [b4e9c293d7].
︙ | ︙ | |||
25 26 27 28 29 30 31 | OFString *__autoreleasing master, *__autoreleasing passwd; processInitQueue(); #define log(s) conoutf(@"init: %@", s) log(@"sdl"); | | | | > | | | > | | | > | 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 | OFString *__autoreleasing master, *__autoreleasing passwd; processInitQueue(); #define log(s) conoutf(@"init: %@", s) log(@"sdl"); const OFOptionsParserOption options[] = { { 'd', @"dedicated", 0, &dedicated, NULL }, { 't', @"window", 0, &windowed, NULL }, { 'w', @"width", 1, NULL, NULL }, { 'h', @"height", 1, NULL, NULL }, { 'u', @"upload-rate", 1, NULL, NULL }, { 'n', @"server-desc", 1, NULL, &sdesc }, { 'i', @"ip", 1, NULL, &ip }, { 'm', @"master", 1, NULL, &master }, { 'p', @"password", 1, NULL, &passwd }, { 'c', @"max-clients", 1, NULL, NULL }, { '\0', nil, 0, NULL, NULL } }; OFOptionsParser *optionsParser = [OFOptionsParser parserWithOptions:options]; OFUnichar option; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { case 'w': _width = (int)optionsParser.argument.longLongValue; |
︙ | ︙ |
Modified src/client.mm from [89ff04e5c2] to [cdd53f348e].
︙ | ︙ | |||
86 87 88 89 90 91 92 | void connects(OFString *servername) { disconnect(1); // reset state addserver(servername); conoutf(@"attempting to connect to %@", servername); | | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | void connects(OFString *servername) { disconnect(1); // reset state addserver(servername); conoutf(@"attempting to connect to %@", servername); ENetAddress address = { ENET_HOST_ANY, CUBE_SERVER_PORT }; @autoreleasepool { if (enet_address_set_host(&address, servername.UTF8String) < 0) { conoutf(@"could not resolve server %@", servername); return; } } |
︙ | ︙ | |||
116 117 118 119 120 121 122 | disconnect(int onlyclean, int async) { if (clienthost) { if (!connecting && !disconnecting) { enet_peer_disconnect(clienthost->peers); enet_host_flush(clienthost); disconnecting = lastmillis; | < > < > < > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | disconnect(int onlyclean, int async) { if (clienthost) { if (!connecting && !disconnecting) { enet_peer_disconnect(clienthost->peers); enet_host_flush(clienthost); disconnecting = lastmillis; } if (clienthost->peers->state != ENET_PEER_STATE_DISCONNECTED) { if (async) return; enet_peer_reset(clienthost->peers); } enet_host_destroy(clienthost); } if (clienthost && !connecting) conoutf(@"disconnected"); clienthost = NULL; connecting = 0; connattempts = 0; disconnecting = 0; |
︙ | ︙ | |||
381 382 383 384 385 386 387 | conoutf(@"attempting to connect..."); connecting = lastmillis; ++connattempts; if (connattempts > 3) { conoutf(@"could not connect to server"); disconnect(); return; | < < > > | 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | conoutf(@"attempting to connect..."); connecting = lastmillis; ++connattempts; if (connattempts > 3) { conoutf(@"could not connect to server"); disconnect(); return; } } while ( clienthost != NULL && enet_host_service(clienthost, &event, 0) > 0) switch (event.type) { case ENET_EVENT_TYPE_CONNECT: conoutf(@"connected to server"); connecting = 0; throttle(); |
︙ | ︙ |
Modified src/clientextras.mm from [0e321e84f3] to [ccc9d61fe8].
1 2 3 4 5 6 7 8 9 10 | // clientextras.cpp: stuff that didn't fit in client.cpp or clientgame.cpp :) #include "cube.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' | | | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // clientextras.cpp: stuff that didn't fit in client.cpp or clientgame.cpp :) #include "cube.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(dynent *d, bool team, OFString *mdlname, bool hellpig, float scale) { int n = 3; float speed = 100.0f; float mz = d->o.z - d->eyeheight + 1.55f * scale; |
︙ | ︙ | |||
33 34 35 36 37 38 39 | if (t < 0 || t > 20000) return; if (t > (r - 1) * 100) { n += 4; if (t > (r + 10) * 100) { t -= (r + 10) * 100; mz -= t * t / 10000000000.0f * t; | < < > > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | if (t < 0 || t > 20000) return; if (t > (r - 1) * 100) { n += 4; if (t > (r + 10) * 100) { t -= (r + 10) * 100; mz -= t * t / 10000000000.0f * t; } } if (mz < -1000) return; // mdl = (((int)d>>6)&1)+1; // mz = d->o.z-d->eyeheight+0.2f; // scale = 1.2f; } else if (d->state == CS_EDITING) { n = 16; |
︙ | ︙ |
Modified src/clientgame.mm from [6689f47248] to [1adcd0a4ff].
︙ | ︙ | |||
66 67 68 69 70 71 72 | if (m_noitemsrail) { d->health = 1; d->ammo[GUN_RIFLE] = 100; } else { if (gamemode == 12) { d->gunselect = GUN_FIST; return; | | < < > > < > < > < > | 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 | if (m_noitemsrail) { d->health = 1; d->ammo[GUN_RIFLE] = 100; } else { if (gamemode == 12) { d->gunselect = GUN_FIST; return; } // eihrul's secret "instafist" mode d->health = 256; if (m_tarena) { int gun1 = rnd(4) + 1; baseammo(d->gunselect = gun1); for (;;) { int gun2 = rnd(4) + 1; if (gun1 != gun2) { baseammo(gun2); break; } } } else if (m_arena) // insta arena { d->ammo[GUN_RIFLE] = 100; } else // efficiency { loopi(4) baseammo(i + 1); d->gunselect = GUN_CG; } d->ammo[GUN_CG] /= 2; } } else { d->ammo[GUN_SG] = 5; } } dynent * newdynent() // create a new blank player or monster { dynent *d = (dynent *)malloc(sizeof(dynent)); d->o.x = 0; |
︙ | ︙ | |||
140 141 142 143 144 145 146 | if (d->state != CS_DEAD) { alive++; if (lastteam && strcmp(lastteam, d->team)) oneteam = false; lastteam = d->team; } else { dead++; | < > | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | if (d->state != CS_DEAD) { alive++; if (lastteam && strcmp(lastteam, d->team)) oneteam = false; lastteam = d->team; } else { dead++; } } int arenarespawnwait = 0; int arenadetectwait = 0; void arenarespawn() |
︙ | ︙ | |||
174 175 176 177 178 179 180 | conoutf( @"team %s is last man standing", lastteam); else conoutf(@"everyone died!"); arenarespawnwait = lastmillis + 5000; arenadetectwait = lastmillis + 10000; player1->roll = 0; | < < > > | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | conoutf( @"team %s is last man standing", lastteam); else conoutf(@"everyone died!"); arenarespawnwait = lastmillis + 5000; arenadetectwait = lastmillis + 10000; player1->roll = 0; } } } void zapdynent(dynent *&d) { if (d) free(d); |
︙ | ︙ | |||
197 198 199 200 201 202 203 | { loopv(players) if (players[i]) { const int lagtime = lastmillis - players[i]->lastupdate; if (lagtime > 1000 && players[i]->state == CS_ALIVE) { players[i]->state = CS_LAGGED; continue; | < > | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | { loopv(players) if (players[i]) { const int lagtime = lastmillis - players[i]->lastupdate; if (lagtime > 1000 && players[i]->state == CS_ALIVE) { players[i]->state = CS_LAGGED; continue; } if (lagtime && players[i]->state != CS_DEAD && (!demoplayback || i != democlientnum)) moveplayer( players[i], 2, false); // use physics to extrapolate // player position } } |
︙ | ︙ | |||
269 270 271 272 273 274 275 | moveplayer(player1, 10, false); } else if (!m_arena && !m_sp && lastmillis - player1->lastaction > 10000) respawn(); } else if (!intermission) { moveplayer(player1, 20, true); checkitems(); | < > | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | moveplayer(player1, 10, false); } else if (!m_arena && !m_sp && lastmillis - player1->lastaction > 10000) respawn(); } else if (!intermission) { moveplayer(player1, 20, true); checkitems(); } c2sinfo(player1); // do this last, to reduce the // effective frame lag } } lastmillis = millis; } |
︙ | ︙ | |||
315 316 317 318 319 320 321 | d->o.z = ents[spawncycle].z; d->yaw = ents[spawncycle].attr1; d->pitch = 0; d->roll = 0; } else { d->o.x = d->o.y = (float)ssize / 2; d->o.z = 4; | < > | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | d->o.z = ents[spawncycle].z; d->yaw = ents[spawncycle].attr1; d->pitch = 0; d->roll = 0; } else { d->o.x = d->o.y = (float)ssize / 2; d->o.z = 4; } entinmap(d); spawnstate(d); d->state = CS_ALIVE; } // movement input code |
︙ | ︙ |
Modified src/clients2c.mm from [15295b6bce] to [e5e63c92dd].
︙ | ︙ | |||
42 43 44 45 46 47 48 | 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) d->o.y += dy < 0 ? r - fy : -(r - fy); // push aside else d->o.x += dx < 0 ? r - fx : -(r - fx); | < > < > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | 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) d->o.y += dy < 0 ? r - fy : -(r - fy); // push aside else d->o.x += dx < 0 ? r - fx : -(r - fx); } int lagtime = lastmillis - d->lastupdate; if (lagtime) { d->plag = (d->plag * 5 + lagtime) / 6; d->lastupdate = lastmillis; } } void localservertoclient( uchar *buf, int len) // processes any updates from the server { if (ENET_NET_TO_HOST_16(*(ushort *)buf) != len) |
︙ | ︙ | |||
297 298 299 300 301 302 303 | case SV_EDITD: case SV_EDITE: { int x = getint(p); int y = getint(p); int xs = getint(p); int ys = getint(p); int v = getint(p); | | | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | case SV_EDITD: case SV_EDITE: { int x = getint(p); int y = getint(p); int xs = getint(p); int ys = getint(p); int v = getint(p); block b = { x, y, xs, ys }; switch (type) { case SV_EDITH: editheightxy(v != 0, getint(p), b); break; case SV_EDITT: edittexxy(v, getint(p), b); break; |
︙ | ︙ |
Modified src/editing.mm from [f5920b6aeb] to [46292a408f].
︙ | ︙ | |||
10 11 12 13 14 15 16 | // the edge of the map block sel; OF_CONSTRUCTOR() { enqueueInit(^{ | | | | | | | | 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 | // the edge of the map block sel; OF_CONSTRUCTOR() { enqueueInit(^{ sel = (block) { variable(@"selx", 0, 0, 4096, &sel.x, NULL, false), variable(@"sely", 0, 0, 4096, &sel.y, NULL, false), variable(@"selxs", 0, 0, 4096, &sel.xs, NULL, false), variable(@"selys", 0, 0, 4096, &sel.ys, NULL, false), }; }); } int selh = 0; bool selset = false; #define loopselxy(b) \ { \ makeundo(); \ loop(x, sel.xs) loop(y, sel.ys) \ { \ sqr *s = S(sel.x + x, sel.y + y); \ b; \ } \ remip(sel); \ } int cx, cy, ch; int curedittex[] = { -1, -1, -1 }; bool dragging = false; int lastx, lasty, lasth; int lasttype = 0, lasttex = 0; sqr rtex; |
︙ | ︙ | |||
114 115 116 117 118 119 120 | #define EDITMP \ if (noteditmode() || multiplayer()) \ return; void selectpos(int x, int y, int xs, int ys) { | | | | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | #define EDITMP \ if (noteditmode() || multiplayer()) \ return; void selectpos(int x, int y, int xs, int ys) { block s = { x, y, xs, ys }; sel = s; selh = 0; correctsel(); } void makesel() { block s = { min(lastx, cx), min(lasty, cy), abs(lastx - cx) + 1, abs(lasty - cy) + 1 }; sel = s; selh = max(lasth, ch); correctsel(); if (selset) rtex = *S(sel.x, sel.y); } |
︙ | ︙ | |||
160 161 162 163 164 165 166 | cx = (int)x; cy = (int)y; if (OUTBORD(cx, cy)) return; sqr *s = S(cx, cy); | > | < < > | | < > > | < > < > | 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 206 207 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 | cx = (int)x; cy = (int)y; if (OUTBORD(cx, cy)) return; sqr *s = S(cx, cy); // selected wall if (fabs(sheight(s, s, z) - z) > 1) { x += x > player1->o.x ? 0.5f : -0.5f; // find right wall cube y += y > player1->o.y ? 0.5f : -0.5f; cx = (int)x; cy = (int)y; if (OUTBORD(cx, cy)) return; } if (dragging) makesel(); const int GRIDSIZE = 5; const float GRIDW = 0.5f; const float GRID8 = 2.0f; const float GRIDS = 2.0f; const int GRIDM = 0x7; // render editing grid for (int ix = cx - GRIDSIZE; ix <= cx + GRIDSIZE; ix++) { for (int iy = cy - GRIDSIZE; iy <= cy + GRIDSIZE; iy++) { if (OUTBORD(ix, iy)) continue; sqr *s = S(ix, iy); if (SOLID(s)) continue; float h1 = sheight(s, s, z); float h2 = sheight(s, SWS(s, 1, 0, ssize), z); float h3 = sheight(s, SWS(s, 1, 1, ssize), z); float h4 = sheight(s, SWS(s, 0, 1, ssize), z); if (s->tag) linestyle(GRIDW, 0xFF, 0x40, 0x40); else if (s->type == FHF || s->type == CHF) linestyle(GRIDW, 0x80, 0xFF, 0x80); else linestyle(GRIDW, 0x80, 0x80, 0x80); block b = { ix, iy, 1, 1 }; box(b, h1, h2, h3, h4); linestyle(GRID8, 0x40, 0x40, 0xFF); if (!(ix & GRIDM)) line(ix, iy, h1, ix, iy + 1, h4); if (!(ix + 1 & GRIDM)) line(ix + 1, iy, h2, ix + 1, iy + 1, h3); if (!(iy & GRIDM)) line(ix, iy, h1, ix + 1, iy, h2); if (!(iy + 1 & GRIDM)) line(ix, iy + 1, h4, ix + 1, iy + 1, h3); } } if (!SOLID(s)) { float ih = sheight(s, s, z); linestyle(GRIDS, 0xFF, 0xFF, 0xFF); block b = { cx, cy, 1, 1 }; box(b, ih, sheight(s, SWS(s, 1, 0, ssize), z), sheight(s, SWS(s, 1, 1, ssize), z), sheight(s, SWS(s, 0, 1, ssize), z)); linestyle(GRIDS, 0xFF, 0x00, 0x00); dot(cx, cy, ih); ch = (int)ih; } if (selset) { linestyle(GRIDS, 0xFF, 0x40, 0x40); box(sel, (float)selh, (float)selh, (float)selh, (float)selh); } } vector<block *> undos; // unlimited undo VARP(undomegs, 0, 1, 10); // bounded by n megs void pruneundos(int maxremain) // bound memory |
︙ | ︙ | |||
312 313 314 315 316 317 318 | if (c >= 0) { uchar *p = hdr.texlists[i]; int t = p[c]; for (int a = c - 1; a >= 0; a--) p[a + 1] = p[a]; p[0] = t; curedittex[i] = -1; | < > < > | 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 | if (c >= 0) { uchar *p = hdr.texlists[i]; int t = p[c]; for (int a = c - 1; a >= 0; a--) p[a + 1] = p[a]; p[0] = t; curedittex[i] = -1; } } } void editdrag(bool isdown) { if (dragging = isdown) { lastx = cx; lasty = cy; lasth = ch; selset = false; tofronttex(); } makesel(); } // the core editing function. all the *xy functions perform the core operations // and are also called directly from the network, the function below it is // strictly triggered locally. They all have very similar structure. |
︙ | ︙ | |||
386 387 388 389 390 391 392 | { EDITSEL; if (type < 0 || type > 3) return; if (type != lasttype) { tofronttex(); lasttype = type; | < > | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 | { EDITSEL; if (type < 0 || type > 3) return; if (type != lasttype) { tofronttex(); lasttype = type; } int atype = type == 3 ? 1 : type; int i = curedittex[atype]; i = i < 0 ? 0 : i + dir; curedittex[atype] = i = min(max(i, 0), 255); int t = lasttex = hdr.texlists[atype][i]; edittexxy(type, t, sel); addmsg(1, 7, SV_EDITT, sel.x, sel.y, sel.xs, sel.ys, type, t); |
︙ | ︙ | |||
420 421 422 423 424 425 426 | if (s->ctex == rtex.ctex) s->ctex = lasttex; break; case 3: if (s->utex == rtex.utex) s->utex = lasttex; break; | < | > | | 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | if (s->ctex == rtex.ctex) s->ctex = lasttex; break; case 3: if (s->utex == rtex.utex) s->utex = lasttex; break; } } block b = { 0, 0, ssize, ssize }; remip(b); } void edittypexy(int type, block &sel) { loopselxy(s->type = type); |
︙ | ︙ | |||
522 523 524 525 526 527 528 | void archvertex(int span, int vert, int delta) { if (!archvinit) { archvinit = true; loop(s, MAXARCHVERT) loop(v, MAXARCHVERT) archverts[s][v] = 0; | < > | 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 | void archvertex(int span, int vert, int delta) { if (!archvinit) { archvinit = true; loop(s, MAXARCHVERT) loop(v, MAXARCHVERT) archverts[s][v] = 0; } if (span >= MAXARCHVERT || vert >= MAXARCHVERT || span < 0 || vert < 0) return; archverts[span][vert] = delta; } void arch(int sidedelta, int _a) |
︙ | ︙ | |||
583 584 585 586 587 588 589 | } VARF( fullbright, 0, 0, 1, if (fullbright) { if (noteditmode()) return; loopi(mipsize) world[i].r = world[i].g = world[i].b = 176; | | | 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | } VARF( fullbright, 0, 0, 1, if (fullbright) { if (noteditmode()) return; loopi(mipsize) world[i].r = world[i].g = world[i].b = 176; }); void edittag(int tag) { EDITSELMP; loopselxy(s->tag = tag); } |
︙ | ︙ |
Modified src/entities.mm from [6e39a8fac1] to [f745b5a428].
1 2 3 4 5 6 7 8 9 | // entities.cpp: map entity related functions (pickup etc.) #include "cube.h" #import "MapModelInfo.h" vector<entity> ents; static OFString *entmdlnames[] = { | | | | | | | | | | | | 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 | // entities.cpp: map entity related functions (pickup etc.) #include "cube.h" #import "MapModelInfo.h" vector<entity> ents; static OFString *entmdlnames[] = { @"shells", @"bullets", @"rockets", @"rrounds", @"health", @"boost", @"g_armour", @"y_armour", @"quad", @"teleporter", }; int triggertime = 0; void renderent(entity &e, OFString *mdlname, float z, float yaw, int frame = 0, int numf = 1, int basetime = 0, float speed = 10.0f) |
︙ | ︙ | |||
59 60 61 62 63 64 65 | 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); | | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | 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); } else { switch (e.attr2) { case 1: case 3: continue; case 2: case 0: |
︙ | ︙ | |||
95 96 97 98 99 100 101 | (float)e.attr3 * 90, (!e.spawned && !triggertime) ? 30 : 0, (e.spawned || !triggertime) ? 1 : 30, triggertime, 35.0f); break; | < < > > > < < | < < | < < | < < | < < | < < | < < | < < | < < | | 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 | (float)e.attr3 * 90, (!e.spawned && !triggertime) ? 30 : 0, (e.spawned || !triggertime) ? 1 : 30, triggertime, 35.0f); break; } } } } } struct itemstat { int add, max, sound; } itemstats[] = { { 10, 50, S_ITEMAMMO }, { 20, 100, S_ITEMAMMO }, { 5, 25, S_ITEMAMMO }, { 5, 25, S_ITEMAMMO }, { 25, 100, S_ITEMHEALTH }, { 50, 200, S_ITEMHEALTH }, { 100, 100, S_ITEMARMOUR }, { 150, 150, S_ITEMARMOUR }, { 20000, 30000, S_ITEMPUP }, }; void baseammo(int gun) { player1->ammo[gun] = itemstats[gun - 1].add * 2; } |
︙ | ︙ | |||
229 230 231 232 233 234 235 | d->o.z = ents[e].z; d->yaw = ents[e].attr1; d->pitch = 0; d->vel.x = d->vel.y = d->vel.z = 0; entinmap(d); playsoundc(S_TELEPORT); break; | < < > > | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | d->o.z = ents[e].z; d->yaw = ents[e].attr1; d->pitch = 0; d->vel.x = d->vel.y = d->vel.z = 0; entinmap(d); playsoundc(S_TELEPORT); break; } } } void pickup(int n, dynent *d) { int np = 1; loopv(players) if (players[i]) np++; |
︙ | ︙ | |||
290 291 292 293 294 295 296 | case TELEPORT: { static int lastteleport = 0; if (lastmillis - lastteleport < 500) break; lastteleport = lastmillis; teleport(n, d); break; | < > | 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | case TELEPORT: { static int lastteleport = 0; if (lastmillis - lastteleport < 500) break; lastteleport = lastmillis; teleport(n, d); break; } case JUMPPAD: { static int lastjumppad = 0; if (lastmillis - lastjumppad < 300) break; lastjumppad = lastmillis; OFVector3D v = OFMakeVector3D((int)(char)ents[n].attr3 / 10.0f, |
︙ | ︙ |
Modified src/monster.mm from [9d16bae907] to [3ac13a2932].
︙ | ︙ | |||
27 28 29 30 31 32 33 | short gun, speed, health, freq, lag, rate, pain, loyalty, mscale, bscale; short painsound, diesound; OFConstantString *name, *mdlname; } monstertypes[NUMMONSTERTYPES] = { | | | | | | | | | | | | | | | | | | 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 | short gun, speed, health, freq, lag, rate, pain, loyalty, mscale, bscale; short painsound, diesound; OFConstantString *name, *mdlname; } monstertypes[NUMMONSTERTYPES] = { { GUN_FIREBALL, 15, 100, 3, 0, 100, 800, 1, 10, 10, S_PAINO, S_DIE1, @"an ogre", @"monster/ogro" }, { GUN_CG, 18, 70, 2, 70, 10, 400, 2, 8, 9, S_PAINR, S_DEATHR, @"a rhino", @"monster/rhino" }, { GUN_SG, 14, 120, 1, 100, 300, 400, 4, 14, 14, S_PAINE, S_DEATHE, @"ratamahatta", @"monster/rat" }, { GUN_RIFLE, 15, 200, 1, 80, 300, 300, 4, 18, 18, S_PAINS, S_DEATHS, @"a slith", @"monster/slith" }, { GUN_RL, 13, 500, 1, 0, 100, 200, 6, 24, 24, S_PAINB, S_DEATHB, @"bauul", @"monster/bauul" }, { GUN_BITE, 22, 50, 3, 0, 100, 400, 1, 12, 15, S_PAINP, S_PIGGR2, @"a hellpig", @"monster/hellpig" }, { 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" }, }; dynent * basicmonster(int type, int yaw, int state, int trigger, int move) { if (type >= NUMMONSTERTYPES) { conoutf(@"warning: unknown monster in spawn: %d", type); |
︙ | ︙ | |||
86 87 88 89 90 91 92 | return m; } void spawnmonster() // spawn a random monster according to freq distribution in DMSP { int n = rnd(TOTMFREQ), type; | | < > > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | return m; } void spawnmonster() // spawn a random monster according to freq distribution in DMSP { int n = rnd(TOTMFREQ), type; for (int i = 0;; i++) { if ((n -= monstertypes[i].freq) < 0) { type = i; break; } } basicmonster(type, rnd(360), M_SEARCH, 1000, 1); } void monsterclear() // called after map start of when toggling edit mode to // reset/spawn all monsters to initial state { |
︙ | ︙ | |||
118 119 120 121 122 123 124 | ents[i].attr2, ents[i].attr1, M_SLEEP, 100, 0); m->o.x = ents[i].x; m->o.y = ents[i].y; m->o.z = ents[i].z; entinmap(m); monstertotal++; } | < > | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | ents[i].attr2, ents[i].attr1, M_SLEEP, 100, 0); m->o.x = ents[i].x; m->o.y = ents[i].y; m->o.z = ents[i].z; entinmap(m); monstertotal++; } } } bool los(float lx, float ly, float lz, float bx, float by, float bz, OFVector3D &v) // height-correct line of sight for monster shooting/seeing { if (OUTBORD((int)lx, (int)ly) || OUTBORD((int)bx, (int)by)) |
︙ | ︙ | |||
154 155 156 157 158 159 160 | break; v.x = x; v.y = y; v.z = rz; x += dx / (float)steps; y += dy / (float)steps; i++; | < > | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | break; v.x = x; v.y = y; v.z = rz; x += dx / (float)steps; y += dy / (float)steps; i++; } return i >= steps; } bool enemylos(dynent *m, OFVector3D &v) { v = m->o; |
︙ | ︙ | |||
199 200 201 202 203 204 205 | void monsteraction( dynent *m) // main AI thinking routine, called every frame for every monster { if (m->enemy->state == CS_DEAD) { m->enemy = player1; m->anger = 0; | < > < > | < > < < | < > > | | < < > | < < < < > > | 200 201 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 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | void monsteraction( dynent *m) // main AI thinking routine, called every frame for every monster { if (m->enemy->state == CS_DEAD) { m->enemy = player1; m->anger = 0; } normalise(m, m->targetyaw); if (m->targetyaw > m->yaw) // slowly turn monster towards his target { m->yaw += curtime * 0.5f; if (m->targetyaw < m->yaw) m->yaw = m->targetyaw; } else { m->yaw -= curtime * 0.5f; if (m->targetyaw > m->yaw) m->yaw = m->targetyaw; } vdist(disttoenemy, vectoenemy, m->o, m->enemy->o); m->pitch = atan2(m->enemy->o.z - m->o.z, disttoenemy) * 180 / PI; // special case: if we run into scenery if (m->blocked) { m->blocked = false; // try to jump over obstackle (rare) if (!rnd(20000 / monstertypes[m->mtype].speed)) m->jumpnext = true; // search for a way around (common) else if (m->trigger < lastmillis && (m->monsterstate != M_HOME || !rnd(5))) { // patented "random walk" AI pathfinding (tm) ;) m->targetyaw += 180 + rnd(180); transition(m, M_SEARCH, 1, 400, 1000); } } float enemyyaw = -(float)atan2(m->enemy->o.x - m->o.x, m->enemy->o.y - m->o.y) / PI * 180 + 180; switch (m->monsterstate) { |
︙ | ︙ | |||
262 263 264 265 266 267 268 | if (disttoenemy < 8 // the better the angle to the player, the // further the monster can see/hear || (disttoenemy < 16 && angle < 135) || (disttoenemy < 32 && angle < 90) || (disttoenemy < 64 && angle < 45) || angle < 10) { transition(m, M_HOME, 1, 500, 200); playsound(S_GRUNT1 + rnd(2), &m->o); | < > < > < > | 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 | if (disttoenemy < 8 // the better the angle to the player, the // further the monster can see/hear || (disttoenemy < 16 && angle < 135) || (disttoenemy < 32 && angle < 90) || (disttoenemy < 64 && angle < 45) || angle < 10) { transition(m, M_HOME, 1, 500, 200); playsound(S_GRUNT1 + rnd(2), &m->o); } break; } case M_AIMING: // this state is the delay between wanting to shoot and // actually firing if (m->trigger < lastmillis) { m->lastaction = 0; m->attacking = true; shoot(m, m->attacktarget); transition(m, M_ATTACKING, 0, 600, 0); } break; case M_HOME: // monster has visual contact, heads straight for player // and may want to shoot at any time m->targetyaw = enemyyaw; if (m->trigger < lastmillis) { OFVector3D target; |
︙ | ︙ | |||
301 302 303 304 305 306 307 | m->attacktarget = target; transition(m, M_AIMING, 0, monstertypes[m->mtype].lag, 10); } else // track player some more { transition(m, M_HOME, 1, monstertypes[m->mtype].rate, 0); | < < < > > > < > > | < | < > | | | > > | | < < > > | < | < | 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 | m->attacktarget = target; transition(m, M_AIMING, 0, monstertypes[m->mtype].lag, 10); } else // track player some more { transition(m, M_HOME, 1, monstertypes[m->mtype].rate, 0); } } } break; } moveplayer(m, 1, false); // use physics to move monster } void monsterpain(dynent *m, int damage, dynent *d) { // a monster hit us if (d->monsterstate) { // guard for RL guys shooting themselves :) if (m != d) { // don't attack straight away, first get angry m->anger++; int anger = m->mtype == d->mtype ? m->anger / 2 : m->anger; if (anger >= monstertypes[m->mtype].loyalty) // monster infight if very angry m->enemy = d; } } else { // player hit us m->anger = 0; m->enemy = d; } // in this state monster won't attack transition(m, M_PAIN, 0, monstertypes[m->mtype].pain, 200); if ((m->health -= damage) <= 0) { m->state = CS_DEAD; m->lastaction = lastmillis; numkilled++; player1->frags = numkilled; playsound(monstertypes[m->mtype].diesound, &m->o); int remain = monstertotal - numkilled; if (remain > 0 && remain <= 5) conoutf(@"only %d monster(s) remaining", remain); } else playsound(monstertypes[m->mtype].painsound, &m->o); } void endsp(bool allkilled) { conoutf(allkilled ? @"you have cleared the map!" : @"you reached the exit!"); |
︙ | ︙ | |||
364 365 366 367 368 369 370 | monsterthink() { if (m_dmsp && spawnremain && lastmillis > nextmonster) { if (spawnremain-- == monstertotal) conoutf(@"The invasion has begun!"); nextmonster = lastmillis + 1000; spawnmonster(); | < > | > | > | | < | | < | | | | > | > | 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 | monsterthink() { if (m_dmsp && spawnremain && lastmillis > nextmonster) { if (spawnremain-- == monstertotal) conoutf(@"The invasion has begun!"); nextmonster = lastmillis + 1000; spawnmonster(); } if (monstertotal && !spawnremain && numkilled == monstertotal) endsp(true); loopv(ents) // equivalent of player entity touch, but only teleports are // used { entity &e = ents[i]; if (e.type != TELEPORT) continue; if (OUTBORD(e.x, e.y)) continue; OFVector3D v = OFMakeVector3D(e.x, e.y, (float)S(e.x, e.y)->floor); loopv(monsters) { if (monsters[i]->state == CS_DEAD) { if (lastmillis - monsters[i]->lastaction < 2000) { monsters[i]->move = 0; moveplayer(monsters[i], 1, false); } } else { v.z += monsters[i]->eyeheight; vdist(dist, t, monsters[i]->o, v); v.z -= monsters[i]->eyeheight; if (dist < 4) teleport( (int)(&e - &ents[0]), monsters[i]); } } } loopv(monsters) if (monsters[i]->state == CS_ALIVE) monsteraction(monsters[i]); } |
︙ | ︙ |
Modified src/physics.mm from [5d3f7bf679] to [cbd2b108e1].
︙ | ︙ | |||
25 26 27 28 29 30 31 | if (fabs(o->o.z - d->o.z) < o->aboveeye + d->eyeheight) return false; if (d->monsterstate) return false; // hack headspace = d->o.z - o->o.z - o->aboveeye - d->eyeheight; if (headspace < 0) headspace = 10; | < > < > | 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 | if (fabs(o->o.z - d->o.z) < o->aboveeye + d->eyeheight) return false; if (d->monsterstate) return false; // hack headspace = d->o.z - o->o.z - o->aboveeye - d->eyeheight; if (headspace < 0) headspace = 10; } return true; } bool cornertest(int mip, int x, int y, int dx, int dy, int &bx, int &by, int &bs) // recursively collide with a mipmapped corner cube { sqr *w = wmip[mip]; int sz = ssize >> mip; bool stest = SOLID(SWS(w, x + dx, y, sz)) && SOLID(SWS(w, x, y + dy, sz)); mip++; x /= 2; y /= 2; if (SWS(wmip[mip], x, y, ssize >> mip)->type == CORNER) { bx = x << mip; by = y << mip; bs = 1 << mip; return cornertest(mip, x, y, dx, dy, bx, by, bs); } return stest; } void mmcollide(dynent *d, float &hi, float &lo) // collide with a mapmodel { loopv(ents) |
︙ | ︙ | |||
128 129 130 131 132 133 134 | 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; | < > < > < > | 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 | 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; } case FHF: // FIXME: too simplistic collision with // slopes, makes it feels like tiny stairs 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) return false; } if (hi - lo < d->eyeheight + d->aboveeye) return false; float headspace = 10; loopv(players) // collide with other players { |
︙ | ︙ | |||
190 191 192 193 194 195 196 | d->o.z = lo + d->eyeheight; // stick on step else if (space > -1.26f) d->o.z += rise; // rise thru stair else return false; } else { d->o.z -= min(min(drop, space), headspace); // gravity | < > < | > < > | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | d->o.z = lo + d->eyeheight; // stick on step else if (space > -1.26f) d->o.z += rise; // rise thru stair else return false; } else { d->o.z -= min(min(drop, space), headspace); // gravity } const float space2 = hi - (d->o.z + d->aboveeye); if (space2 < 0) { if (space2 < -0.1) return false; // hack alert! d->o.z = hi - d->aboveeye; // glue to ceiling d->vel.z = 0; // cancel out jumping velocity } d->onfloor = d->o.z - d->eyeheight - lo < 0.001f; } return true; } float rad(float x) { return x * 3.14159f / 180; |
︙ | ︙ | |||
225 226 227 228 229 230 231 | { if (curtime >= MINFRAMETIME) { int faketime = curtime + physicsfraction; physicsrepeat = faketime / MINFRAMETIME; physicsfraction = faketime - physicsrepeat * MINFRAMETIME; } else { physicsrepeat = 1; | < > | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | { if (curtime >= MINFRAMETIME) { int faketime = curtime + physicsfraction; physicsrepeat = faketime / MINFRAMETIME; physicsfraction = faketime - physicsrepeat * MINFRAMETIME; } else { physicsrepeat = 1; } } // main physics routine, moves a player/monster for a curtime step // moveres indicated the physics precision (which is lower for monsters and // multiplayer prediction) local is false for multiplayer prediction void |
︙ | ︙ | |||
248 249 250 251 252 253 254 | d.y = (float)(pl->move * sin(rad(pl->yaw - 90))); d.z = 0; if (floating || water) { d.x *= (float)cos(rad(pl->pitch)); d.y *= (float)cos(rad(pl->pitch)); d.z = (float)(pl->move * sin(rad(pl->pitch))); | < > | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | d.y = (float)(pl->move * sin(rad(pl->yaw - 90))); d.z = 0; if (floating || water) { d.x *= (float)cos(rad(pl->pitch)); d.y *= (float)cos(rad(pl->pitch)); d.z = (float)(pl->move * sin(rad(pl->pitch))); } d.x += (float)(pl->strafe * cos(rad(pl->yaw - 180))); d.y += (float)(pl->strafe * sin(rad(pl->yaw - 180))); const float speed = curtime / (water ? 2000.0f : 1000.0f) * pl->maxspeed; const float friction = |
︙ | ︙ | |||
283 284 285 286 287 288 289 290 291 292 | } } else // apply velocity with collision { if (pl->onfloor || water) { if (pl->jumpnext) { pl->jumpnext = false; pl->vel.z = 1.7f; // physics impulse upwards if (water) { pl->vel.x /= 8; pl->vel.y /= 8; | > > < < > | | | < < > < > > | < > < > < > < > < > < > < > < > | 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 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 | } } else // apply velocity with collision { if (pl->onfloor || water) { if (pl->jumpnext) { pl->jumpnext = false; pl->vel.z = 1.7f; // physics impulse upwards // dampen velocity change even harder, gives // correct water feel if (water) { pl->vel.x /= 8; pl->vel.y /= 8; } if (local) playsoundc(S_JUMP); else if (pl->monsterstate) playsound(S_JUMP, &pl->o); } else if (pl->timeinair > 800) { // if we land after long time must have been a // high jump, make thud sound if (local) playsoundc(S_LAND); else if (pl->monsterstate) playsound(S_LAND, &pl->o); } pl->timeinair = 0; } else { pl->timeinair += curtime; } const float gravity = 20; const float f = 1.0f / moveres; // incorrect, but works fine float dropf = ((gravity - 1) + pl->timeinair / 15.0f); // float slowly down in water if (water) { dropf = 5; pl->timeinair = 0; } const float drop = dropf * curtime / gravity / 100 / moveres; // at high fps, gravity kicks in too fast const float rise = speed / moveres / 1.2f; // extra smoothness when lifting up stairs loopi(moveres) // discrete steps collision detection & sliding { // try move forward pl->o.x += f * d.x; pl->o.y += f * d.y; pl->o.z += f * d.z; if (collide(pl, false, drop, rise)) continue; // player stuck, try slide along y axis pl->blocked = true; pl->o.x -= f * d.x; if (collide(pl, false, drop, rise)) { d.x = 0; continue; } pl->o.x += f * d.x; // still stuck, try x axis pl->o.y -= f * d.y; if (collide(pl, false, drop, rise)) { d.y = 0; continue; } pl->o.y += f * d.y; // try just dropping down pl->moving = false; pl->o.x -= f * d.x; pl->o.y -= f * d.y; if (collide(pl, false, drop, rise)) { d.y = d.x = 0; continue; } pl->o.z -= f * d.z; break; } } // detect wether player is outside map, used for skipping zbuffer clear // mostly if (pl->o.x < 0 || pl->o.x >= ssize || pl->o.y < 0 || pl->o.y > ssize) { pl->outsidemap = true; } else { sqr *s = S((int)pl->o.x, (int)pl->o.y); pl->outsidemap = SOLID(s) || pl->o.z < s->floor - (s->type == FHF ? s->vdelta / 4 : 0) || pl->o.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 { pl->roll += pl->strafe * curtime / -30.0f; if (pl->roll > maxroll) pl->roll = (float)maxroll; if (pl->roll < -maxroll) pl->roll = (float)-maxroll; } // play sounds on water transitions if (!pl->inwater && water) { playsound(S_SPLASH2, &pl->o); pl->vel.z = 0; } else if (pl->inwater && !water) |
︙ | ︙ |
Modified src/rendercubes.mm from [e0804e2cb2] to [50158effb9].
︙ | ︙ | |||
43 44 45 46 47 48 49 | v.x = v1; \ v.y = v2; \ v.z = v3; \ v.r = ls->r; \ v.g = ls->g; \ v.b = ls->b; \ v.a = 255; \ | < > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 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; |
︙ | ︙ | |||
77 78 79 80 81 82 83 | } #define stripend() \ { \ if (floorstrip || deltastrip) { \ addstrip(ogltex, firstindex, curvert - firstindex); \ floorstrip = deltastrip = false; \ | | < > < > | 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 109 110 | } #define stripend() \ { \ if (floorstrip || deltastrip) { \ addstrip(ogltex, firstindex, curvert - firstindex); \ floorstrip = deltastrip = false; \ } \ } void finishstrips() { stripend(); } sqr sbright, sdark; VAR(lighterror, 1, 8, 100); void render_flat(int wtex, int x, int y, int size, int h, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil) // floor/ceil quads { vertcheck(); if (showm) { l3 = l1 = &sbright; l4 = l2 = &sdark; } int sx, sy; int gltex = lookuptexture(wtex, &sx, &sy); float xf = TEXTURESCALE / sx; float yf = TEXTURESCALE / sy; float xs = size * xf; float ys = size * yf; |
︙ | ︙ | |||
124 125 126 127 128 129 130 | floorstrip = true; if (isceil) { vert(x + size, h, y, l2, xo + xs, yo); vert(x, h, y, l1, xo, yo); } else { vert(x, h, y, l1, xo, yo); vert(x + size, h, y, l2, xo + xs, yo); | < > | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | floorstrip = true; if (isceil) { vert(x + size, h, y, l2, xo + xs, yo); vert(x, h, y, l1, xo, yo); } else { vert(x, h, y, l1, xo, yo); vert(x + size, h, y, l2, xo + xs, yo); } ol3r = l1->r; ol3g = l1->g; ol3b = l1->b; ol4r = l2->r; ol4g = l2->g; ol4b = l2->b; } else // continue strip |
︙ | ︙ | |||
153 154 155 156 157 158 159 | ol3r = p3[0]; ol3g = p3[1]; ol3b = p3[2]; uchar *p4 = (uchar *)(&verts[curvert - 2].r); ol4r = p4[0]; ol4g = p4[1]; ol4b = p4[2]; | < < > > < > < > | 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 | ol3r = p3[0]; ol3g = p3[1]; ol3b = p3[2]; uchar *p4 = (uchar *)(&verts[curvert - 2].r); ol4r = p4[0]; ol4g = p4[1]; ol4b = p4[2]; } } if (isceil) { vert(x + size, h, y + size, l3, xo + xs, yo + ys); vert(x, h, y + size, l4, xo, yo + ys); } else { vert(x, h, y + size, l4, xo, yo + ys); vert(x + size, h, y + size, l3, xo + xs, yo + ys); } oy = y; nquads++; } void render_flatdelta(int wtex, int x, int y, int size, float h1, float h2, float h3, float h4, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil) // floor/ceil quads on a slope { vertcheck(); if (showm) { l3 = l1 = &sbright; l4 = l2 = &sdark; } int sx, sy; int gltex = lookuptexture(wtex, &sx, &sy); float xf = TEXTURESCALE / sx; float yf = TEXTURESCALE / sy; float xs = size * xf; float ys = size * yf; |
︙ | ︙ | |||
203 204 205 206 207 208 209 | deltastrip = true; if (isceil) { vertf((float)x + size, h2, (float)y, l2, xo + xs, yo); vertf((float)x, h1, (float)y, l1, xo, yo); } else { vertf((float)x, h1, (float)y, l1, xo, yo); vertf((float)x + size, h2, (float)y, l2, xo + xs, yo); | < > < > < > | 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 229 230 231 232 233 234 | deltastrip = true; if (isceil) { vertf((float)x + size, h2, (float)y, l2, xo + xs, yo); vertf((float)x, h1, (float)y, l1, xo, yo); } else { vertf((float)x, h1, (float)y, l1, xo, yo); vertf((float)x + size, h2, (float)y, l2, xo + xs, yo); } ol3r = l1->r; ol3g = l1->g; ol3b = l1->b; ol4r = l2->r; ol4g = l2->g; ol4b = l2->b; } if (isceil) { vertf( (float)x + size, h3, (float)y + size, l3, xo + xs, yo + ys); vertf((float)x, h4, (float)y + size, l4, xo, yo + ys); } else { vertf((float)x, h4, (float)y + size, l4, xo, yo + ys); vertf( (float)x + size, h3, (float)y + size, l3, xo + xs, yo + ys); } oy = y; nquads++; } void render_2tris(sqr *h, sqr *s, int x1, int y1, int x2, int y2, int x3, int y3, |
︙ | ︙ | |||
272 273 274 275 276 277 278 | } else { if (h1) render_2tris( h1, s, x, y, x + size, y, x, y + size, s, t, u); if (h2) render_2tris(h2, s, x + size, y, x + size, y + size, x, y + size, t, u, v); | < > < > < > | 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 310 311 312 313 314 315 316 317 318 | } else { if (h1) render_2tris( h1, s, x, y, x + size, y, x, y + size, s, t, u); if (h2) render_2tris(h2, s, x + size, y, x + size, y + size, x, y + size, t, u, v); } } void render_square(int wtex, float floor1, float floor2, float ceil1, float ceil2, int x1, int y1, int x2, int y2, int size, sqr *l1, sqr *l2, bool flip) // wall quads { stripend(); vertcheck(); if (showm) { l1 = &sbright; l2 = &sdark; } int sx, sy; int gltex = lookuptexture(wtex, &sx, &sy); float xf = TEXTURESCALE / sx; float yf = TEXTURESCALE / sy; float xs = size * xf; float xo = xf * (x1 == x2 ? min(y1, y2) : min(x1, x2)); if (!flip) { vertf((float)x2, ceil2, (float)y2, l2, xo + xs, -yf * ceil2); vertf((float)x1, ceil1, (float)y1, l1, xo, -yf * ceil1); vertf((float)x2, floor2, (float)y2, l2, xo + xs, -floor2 * yf); vertf((float)x1, floor1, (float)y1, l1, xo, -floor1 * yf); } else { vertf((float)x1, ceil1, (float)y1, l1, xo, -yf * ceil1); vertf((float)x2, ceil2, (float)y2, l2, xo + xs, -yf * ceil2); vertf((float)x1, floor1, (float)y1, l1, xo, -floor1 * yf); vertf((float)x2, floor2, (float)y2, l2, xo + xs, -floor2 * yf); } nquads++; addstrip(gltex, curvert - 4, 4); } int wx1, wy1, wx2, wy2; |
︙ | ︙ | |||
371 372 373 374 375 376 377 | for (int yy = wy1; yy < wy2; yy += watersubdiv) { float xo = xf * (xx + t2); float yo = yf * (yy + t2); if (yy == wy1) { vertw(xx, hf, yy, &dl, dx(xo), dy(yo), t1); vertw(xx + watersubdiv, hf, yy, &dl, dx(xo + xs), dy(yo), t1); | < > < > < > | 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 | for (int yy = wy1; yy < wy2; yy += watersubdiv) { float xo = xf * (xx + t2); float yo = yf * (yy + t2); if (yy == wy1) { vertw(xx, hf, yy, &dl, dx(xo), dy(yo), t1); vertw(xx + watersubdiv, hf, yy, &dl, dx(xo + xs), dy(yo), t1); } vertw(xx, hf, yy + watersubdiv, &dl, dx(xo), dy(yo + ys), t1); vertw(xx + watersubdiv, hf, yy + watersubdiv, &dl, dx(xo + xs), dy(yo + ys), t1); } int n = (wy2 - wy1 - 1) / watersubdiv; nquads += n; n = (n + 2) * 2; glDrawArrays(GL_TRIANGLE_STRIP, curvert -= n, n); } glDisable(GL_BLEND); glDepthMask(GL_TRUE); return nquads; } |
︙ | ︙ | |||
408 409 410 411 412 413 414 | wx1 = x; if (y < wy1) wy1 = y; if (x2 > wx2) wx2 = x2; if (y2 > wy2) wy2 = y2; | < > | 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 | wx1 = x; if (y < wy1) wy1 = y; if (x2 > wx2) wx2 = x2; if (y2 > wy2) wy2 = y2; } } void resetcubes() { if (!verts) reallocv(); floorstrip = deltastrip = false; wx1 = -1; nquads = 0; sbright.r = sbright.g = sbright.b = 255; sdark.r = sdark.g = sdark.b = 0; } |
Modified src/renderextras.mm from [0c686b4d39] to [f6d88ed878].
︙ | ︙ | |||
94 95 96 97 98 99 100 | if (!sinit) { loopi(MAXSPHERES) { spheres[i].next = sempty; sempty = &spheres[i]; } sinit = true; | < > < > | 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 | if (!sinit) { loopi(MAXSPHERES) { spheres[i].next = sempty; sempty = &spheres[i]; } sinit = true; } if (sempty) { sphere *p = sempty; sempty = p->next; p->o = o; p->max = max; p->size = 1; p->type = type; p->next = slist; slist = p; } } void renderspheres(int time) { glDepthMask(GL_FALSE); glEnable(GL_BLEND); |
︙ | ︙ | |||
135 136 137 138 139 140 141 | if (p->size > p->max) { *pp = p->next; p->next = sempty; sempty = p; } else { p->size += time / 100.0f; pp = &p->next; | < < > > | | | | | | | | | | | | | | | | | | | | | | | | 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 | if (p->size > p->max) { *pp = p->next; p->next = sempty; sempty = p; } else { p->size += time / 100.0f; pp = &p->next; } } glDisable(GL_BLEND); glDepthMask(GL_TRUE); } string closeent; OFString *entnames[] = { @"none?", @"light", @"playerstart", @"shells", @"bullets", @"rockets", @"riflerounds", @"health", @"healthboost", @"greenarmour", @"yellowarmour", @"quaddamage", @"teleport", @"teledest", @"mapmodel", @"monster", @"trigger", @"jumppad", @"?", @"?", @"?", @"?", @"?", }; void renderents() // show sparkly thingies for map entities in edit mode { closeent[0] = 0; if (!editmode) |
︙ | ︙ | |||
206 207 208 209 210 211 212 | { @autoreleasepool { static OFString *lastsky = @""; if ([lastsky isEqual:basename]) return; | | | | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | { @autoreleasepool { static OFString *lastsky = @""; if ([lastsky isEqual:basename]) return; static const OFString *side[] = { @"ft", @"bk", @"lf", @"rt", @"dn", @"up" }; int texnum = 14; loopi(6) { OFString *path = [OFString stringWithFormat:@"packages/%@_%@.jpg", basename, side[i]]; |
︙ | ︙ | |||
332 333 334 335 336 337 338 | readmatrices(); if (editmode) { if (cursordepth == 1.0f) worldpos = player1->o; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); cursorupdate(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | < > | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | readmatrices(); if (editmode) { if (cursordepth == 1.0f) worldpos = player1->o; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); cursorupdate(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } glDisable(GL_DEPTH_TEST); invertperspective(); glPushMatrix(); glOrtho(0, VIRTW, VIRTH, 0, -1, 1); glEnable(GL_BLEND); |
︙ | ︙ | |||
438 439 440 441 442 443 444 | drawicon( (float)(player1->armourtype * 64), 0, 620, 1650); int g = player1->gunselect; int r = 64; if (g > 2) { g -= 3; r = 128; | < > | 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | drawicon( (float)(player1->armourtype * 64), 0, 620, 1650); int g = player1->gunselect; int r = 64; if (g > 2) { g -= 3; r = 128; } drawicon((float)(g * 64), (float)r, 1220, 1650); glPopMatrix(); } glDepthMask(GL_TRUE); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); } |
Modified src/rendergl.mm from [5b95ce281e] to [9007a349cc].
︙ | ︙ | |||
106 107 108 109 110 111 112 | SDL_FreeSurface(s); s = converted; } @finally { SDL_FreeFormat(format); } } | > > > | | > > | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | SDL_FreeSurface(s); s = converted; } @finally { SDL_FreeFormat(format); } } #if 0 loopi(s->w * s->h * 3) { uchar *p = (uchar *)s->pixels + i; *p = 255 - *p; } #endif glBindTexture(GL_TEXTURE_2D, tnum); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); glTexParameteri( |
︙ | ︙ | |||
260 261 262 263 264 265 266 | if (hasoverbright) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); | < > | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | if (hasoverbright) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); } } int skyoglid; struct strip { int tex, start, num; }; |
︙ | ︙ | |||
346 347 348 349 350 351 352 | int xtraverts; VAR(fog, 64, 180, 1024); VAR(fogcolour, 0, 0x8099B3, 0xFFFFFF); VARP(hudgun, 0, 1, 1); | | | | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | 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) { rendermodel(hudgunnames[player1->gunselect], start, end, 0, 1.0f, player1->o.x, player1->o.z, player1->o.y, player1->yaw + 90, player1->pitch, false, 1.0f, speed, 0, base); |
︙ | ︙ | |||
378 379 380 381 382 383 384 | int rtime = reloadtime(player1->gunselect); if (player1->lastaction && player1->lastattackgun == player1->gunselect && lastmillis - player1->lastaction < rtime) { drawhudmodel(7, 18, rtime / 18.0f, player1->lastaction); } else { drawhudmodel(6, 1, 100, 0); | < > | | | < > | 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 | int rtime = reloadtime(player1->gunselect); if (player1->lastaction && player1->lastattackgun == player1->gunselect && lastmillis - player1->lastaction < rtime) { drawhudmodel(7, 18, rtime / 18.0f, player1->lastaction); } else { drawhudmodel(6, 1, 100, 0); } glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fovy, aspect, 0.15f, farplane); glMatrixMode(GL_MODELVIEW); glDisable(GL_CULL_FACE); } void gl_drawframe(int w, int h, float curfps) { float hf = hdr.waterlevel - 0.3f; float fovy = (float)fov * h / w; float aspect = w / (float)h; bool underwater = player1->o.z < hf; glFogi(GL_FOG_START, (fog + 64) / 8); glFogi(GL_FOG_END, fog); float fogc[4] = { (fogcolour >> 16) / 256.0f, ((fogcolour >> 8) & 255) / 256.0f, (fogcolour & 255) / 256.0f, 1.0f }; glFogfv(GL_FOG_COLOR, fogc); glClearColor(fogc[0], fogc[1], fogc[2], 1.0f); if (underwater) { fovy += (float)sin(lastmillis / 1000.0) * 2.0f; aspect += (float)sin(lastmillis / 1000.0 + PI) * 0.1f; glFogi(GL_FOG_START, 0); glFogi(GL_FOG_END, (fog + 96) / 8); } glClear((player1->outsidemap ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); int farplane = fog * 5 / 2; |
︙ | ︙ |
Modified src/renderparticles.mm from [9f00935137] to [b42cd85412].
︙ | ︙ | |||
21 22 23 24 25 26 27 | if (!parinit) { loopi(MAXPARTICLES) { particles[i].next = parempty; parempty = &particles[i]; } parinit = true; | < > < > | 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 | if (!parinit) { loopi(MAXPARTICLES) { particles[i].next = parempty; parempty = &particles[i]; } parinit = true; } if (parempty) { particle *p = parempty; parempty = p->next; p->o = o; p->d = d; p->fade = fade; p->type = type; p->millis = lastmillis; p->next = parlist; parlist = p; } } VAR(demotracking, 0, 0, 1); VARP(particlesize, 20, 100, 500); OFVector3D right, up; |
︙ | ︙ | |||
65 66 67 68 69 70 71 | glDisable(GL_FOG); struct parttype { float r, g, b; int gr, tex; float sz; } parttypes[] = { | | | | > | | | | | | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | glDisable(GL_FOG); 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 (particle *p, **pp = &parlist; p = *pp;) { parttype *pt = &parttypes[p->type]; |
︙ | ︙ |
Modified src/rendertext.mm from [c20068be3f] to [d117eaf6b5].
1 2 3 4 5 | // rendertext.cpp: based on Don's gl_text.cpp #include "cube.h" short char_coords[96][4] = { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | // rendertext.cpp: based on Don's gl_text.cpp #include "cube.h" short char_coords[96][4] = { { 0, 0, 25, 64 }, //! { 25, 0, 54, 64 }, //" { 54, 0, 107, 64 }, // # { 107, 0, 148, 64 }, //$ { 148, 0, 217, 64 }, //% { 217, 0, 263, 64 }, //& { 263, 0, 280, 64 }, //' { 280, 0, 309, 64 }, //( { 309, 0, 338, 64 }, //) { 338, 0, 379, 64 }, //* { 379, 0, 432, 64 }, //+ { 432, 0, 455, 64 }, //, { 455, 0, 484, 64 }, //- { 0, 64, 21, 128 }, //. { 23, 64, 52, 128 }, /// { 52, 64, 93, 128 }, // 0 { 93, 64, 133, 128 }, // 1 { 133, 64, 174, 128 }, // 2 { 174, 64, 215, 128 }, // 3 { 215, 64, 256, 128 }, // 4 { 256, 64, 296, 128 }, // 5 { 296, 64, 337, 128 }, // 6 { 337, 64, 378, 128 }, // 7 { 378, 64, 419, 128 }, // 8 { 419, 64, 459, 128 }, // 9 { 459, 64, 488, 128 }, //: { 0, 128, 29, 192 }, //; { 29, 128, 81, 192 }, //< { 81, 128, 134, 192 }, //= { 134, 128, 186, 192 }, //> { 186, 128, 221, 192 }, //? { 221, 128, 285, 192 }, //@ { 285, 128, 329, 192 }, // A { 329, 128, 373, 192 }, // B { 373, 128, 418, 192 }, // C { 418, 128, 467, 192 }, // D { 0, 192, 40, 256 }, // E { 40, 192, 77, 256 }, // F { 77, 192, 127, 256 }, // G { 127, 192, 175, 256 }, // H { 175, 192, 202, 256 }, // I { 202, 192, 231, 256 }, // J { 231, 192, 275, 256 }, // K { 275, 192, 311, 256 }, // L { 311, 192, 365, 256 }, // M { 365, 192, 413, 256 }, // N { 413, 192, 463, 256 }, // O { 1, 256, 38, 320 }, // P { 38, 256, 89, 320 }, // Q { 89, 256, 133, 320 }, // R { 133, 256, 176, 320 }, // S { 177, 256, 216, 320 }, // T { 217, 256, 263, 320 }, // U { 263, 256, 307, 320 }, // V { 307, 256, 370, 320 }, // W { 370, 256, 414, 320 }, // X { 414, 256, 453, 320 }, // Y { 453, 256, 497, 320 }, // Z { 0, 320, 29, 384 }, //[ { 29, 320, 58, 384 }, //"\" { 59, 320, 87, 384 }, //] { 87, 320, 139, 384 }, //^ { 139, 320, 180, 384 }, //_ { 180, 320, 221, 384 }, //` { 221, 320, 259, 384 }, // a { 259, 320, 299, 384 }, // b { 299, 320, 332, 384 }, // c { 332, 320, 372, 384 }, // d { 372, 320, 411, 384 }, // e { 411, 320, 433, 384 }, // f { 435, 320, 473, 384 }, // g { 0, 384, 40, 448 }, // h { 40, 384, 56, 448 }, // i { 58, 384, 80, 448 }, // j { 80, 384, 118, 448 }, // k { 118, 384, 135, 448 }, // l { 135, 384, 197, 448 }, // m { 197, 384, 238, 448 }, // n { 238, 384, 277, 448 }, // o { 277, 384, 317, 448 }, // p { 317, 384, 356, 448 }, // q { 357, 384, 384, 448 }, // r { 385, 384, 417, 448 }, // s { 417, 384, 442, 448 }, // t { 443, 384, 483, 448 }, // u { 0, 448, 38, 512 }, // v { 38, 448, 90, 512 }, // w { 90, 448, 128, 512 }, // x { 128, 448, 166, 512 }, // y { 166, 448, 200, 512 }, // z { 200, 448, 241, 512 }, //{ { 241, 448, 270, 512 }, //| { 270, 448, 310, 512 }, //} { 310, 448, 363, 512 }, //~ }; int text_width(OFString *string) { @autoreleasepool { const char *str = string.UTF8String; |
︙ | ︙ |
Modified src/rndmap.mm from [db18b3b402] to [3e8d55fcae].
︙ | ︙ | |||
69 70 71 72 73 74 75 | void perlinarea(block &b, int scale, int seed, int psize) { srand(seed); seed = rnd(10000); if (!scale) scale = 10; | | < > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | void perlinarea(block &b, int scale, int seed, int psize) { srand(seed); seed = rnd(10000); 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++) { 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.mm from [d7af13e4bd] to [518f13ae58].
︙ | ︙ | |||
67 68 69 70 71 72 73 | void stop() { if (f) { if (demorecording) gzputi(-1); gzclose(f); | < > | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | void stop() { if (f) { if (demorecording) gzputi(-1); gzclose(f); } f = NULL; demorecording = false; demoplayback = false; demoloading = false; loopv(playerhistory) zapdynent(playerhistory[i]); playerhistory.setsize(0); } |
︙ | ︙ |
Modified src/server.mm from [2b7d5c9bfe] to [8f47418a23].
︙ | ︙ | |||
16 17 18 19 20 21 22 | }; vector<client> clients; int maxclients = 8; static OFString *smapname; | | < > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | }; vector<client> clients; int maxclients = 8; static OFString *smapname; // server side version of "entity" type struct server_entity { bool spawned; int spawnsecs; }; vector<server_entity> sents; bool notgotitems = |
︙ | ︙ | |||
64 65 66 67 68 69 70 | if (!packet) return; switch (clients[n].type) { case ST_TCPIP: { enet_peer_send(clients[n].peer, 0, packet); bsend += packet->dataLength; break; | < > < > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | if (!packet) return; switch (clients[n].type) { case ST_TCPIP: { enet_peer_send(clients[n].peer, 0, packet); bsend += packet->dataLength; break; } case ST_LOCAL: localservertoclient(packet->data, packet->dataLength); break; } } void send2(bool rel, int cn, int a, int b) { ENetPacket *packet = enet_packet_create(NULL, 32, rel ? ENET_PACKET_FLAG_RELIABLE : 0); |
︙ | ︙ | |||
133 134 135 136 137 138 139 | { if (i >= (uint)sents.length()) return; if (sents[i].spawned) { sents[i].spawned = false; sents[i].spawnsecs = sec; send2(true, sender, SV_ITEMACC, i); | < > | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | { if (i >= (uint)sents.length()) return; if (sents[i].spawned) { sents[i].spawned = false; sents[i].spawnsecs = sec; send2(true, sender, SV_ITEMACC, i); } } void resetvotes() { loopv(clients) clients[i].mapvote[0] = 0; } |
︙ | ︙ | |||
186 187 188 189 190 191 192 | void process(ENetPacket *packet, int sender) // sender may be -1 { if (ENET_NET_TO_HOST_16(*(ushort *)packet->data) != packet->dataLength) { disconnect_client(sender, "packet length"); return; | < > | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | void process(ENetPacket *packet, int sender) // sender may be -1 { if (ENET_NET_TO_HOST_16(*(ushort *)packet->data) != packet->dataLength) { disconnect_client(sender, "packet length"); return; } uchar *end = packet->data + packet->dataLength; uchar *p = packet->data + 2; char text[MAXTRANS]; int cn = -1, type; while (p < end) |
︙ | ︙ | |||
231 232 233 234 235 236 237 | break; } case SV_ITEMLIST: { int n; while ((n = getint(p)) != -1) if (notgotitems) { | | < > < > | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | break; } case SV_ITEMLIST: { int n; while ((n = getint(p)) != -1) if (notgotitems) { server_entity se = { false, 0 }; while (sents.length() <= n) sents.add(se); sents[n].spawned = true; } notgotitems = false; break; } case SV_ITEMPICKUP: { int n = getint(p); pickup(n, getint(p), sender); break; } case SV_PING: send2(false, cn, SV_PONG, getint(p)); break; case SV_POS: { cn = getint(p); if (cn < 0 || cn >= clients.length() || clients[cn].type == ST_EMPTY) { disconnect_client(sender, "client num"); return; } int size = msgsizelookup(type); assert(size != -1); loopi(size - 2) getint(p); break; } case SV_SENDMAP: { |
︙ | ︙ | |||
282 283 284 285 286 287 288 | case SV_EXT: // allows for new features that require no server // updates { for (int n = getint(p); n; n--) getint(p); break; | < > < > < < > > < > | 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 310 311 | case SV_EXT: // allows for new features that require no server // updates { for (int n = getint(p); n; n--) getint(p); break; } default: { int size = msgsizelookup(type); if (size == -1) { disconnect_client(sender, "tag type"); return; } loopi(size - 1) getint(p); } } if (p > end) { disconnect_client(sender, "end of packet"); return; } multicast(packet, sender); } void send_welcome(int n) { ENetPacket *packet = |
︙ | ︙ | |||
361 362 363 364 365 366 367 | void checkintermission() { if (!minremain) { interm = lastsec + 10; mapend = lastsec + 1000; | < > | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | void checkintermission() { if (!minremain) { interm = lastsec + 10; mapend = lastsec + 1000; } send2(true, -1, SV_TIMEUP, minremain--); } void startintermission() { minremain = 0; |
︙ | ︙ | |||
402 403 404 405 406 407 408 | loopv(sents) // spawn entities when timer reached { if (sents[i].spawnsecs && (sents[i].spawnsecs -= seconds - lastsec) <= 0) { sents[i].spawnsecs = 0; sents[i].spawned = true; send2(true, -1, SV_ITEMSPAWN, i); | < > < > | 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 | loopv(sents) // spawn entities when timer reached { if (sents[i].spawnsecs && (sents[i].spawnsecs -= seconds - lastsec) <= 0) { sents[i].spawnsecs = 0; sents[i].spawned = true; send2(true, -1, SV_ITEMSPAWN, i); } } lastsec = seconds; if ((mode > 1 || (mode == 0 && nonlocalclients)) && seconds > mapend - minremain * 60) checkintermission(); if (interm && seconds > interm) { interm = 0; loopv(clients) if (clients[i].type != ST_EMPTY) { send2(true, i, SV_MAPRELOAD, 0); // ask a client to trigger map reload mapreload = true; break; } } resetserverifempty(); if (!isdedicated) return; // below is network only int numplayers = 0; |
︙ | ︙ | |||
444 445 446 447 448 449 450 | laststatus = seconds; if (nonlocalclients || bsend || brec) printf("status: %d remote clients, %.1f send, %.1f rec " "(K/sec)\n", nonlocalclients, bsend / 60.0f / 1024, brec / 60.0f / 1024); bsend = brec = 0; | < > | 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 | laststatus = seconds; if (nonlocalclients || bsend || brec) printf("status: %d remote clients, %.1f send, %.1f rec " "(K/sec)\n", nonlocalclients, bsend / 60.0f / 1024, brec / 60.0f / 1024); bsend = brec = 0; } ENetEvent event; if (enet_host_service(serverhost, &event, timeout) > 0) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: { client &c = addclient(); c.type = ST_TCPIP; |
︙ | ︙ | |||
480 481 482 483 484 485 486 | break; printf("disconnected client (%s)\n", clients[(intptr_t)event.peer->data].hostname); clients[(intptr_t)event.peer->data].type = ST_EMPTY; send2(true, -1, SV_CDIS, (intptr_t)event.peer->data); event.peer->data = (void *)-1; break; | < | > | < < > | 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 | break; printf("disconnected client (%s)\n", clients[(intptr_t)event.peer->data].hostname); clients[(intptr_t)event.peer->data].type = ST_EMPTY; send2(true, -1, SV_CDIS, (intptr_t)event.peer->data); event.peer->data = (void *)-1; break; } if (numplayers > maxclients) disconnect_client(lastconnect, "maxclients reached"); } #ifndef _WIN32 fflush(stdout); #endif } void cleanupserver() |
︙ | ︙ | |||
524 525 526 527 528 529 530 | { serverpassword = passwd; maxclients = maxcl; servermsinit(master ? master : @"wouter.fov120.com/cube/masterserver/", sdesc, dedicated); if (isdedicated = dedicated) { | | | < > < | > | 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 | { serverpassword = passwd; maxclients = maxcl; servermsinit(master ? master : @"wouter.fov120.com/cube/masterserver/", sdesc, dedicated); if (isdedicated = dedicated) { ENetAddress address = { ENET_HOST_ANY, CUBE_SERVER_PORT }; @autoreleasepool { if (ip.length > 0 && enet_address_set_host(&address, ip.UTF8String) < 0) printf("WARNING: server ip not resolved"); } serverhost = enet_host_create(&address, MAXCLIENTS, 0, uprate); if (!serverhost) fatal(@"could not create server host\n"); loopi(MAXCLIENTS) serverhost->peers[i].data = (void *)-1; } resetserverifempty(); // do not return, this becomes main loop if (isdedicated) { #ifdef _WIN32 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); #endif printf("dedicated server started, waiting for " "clients...\nCtrl-C to exit\n\n"); atexit(cleanupserver); atexit(enet_deinitialize); for (;;) serverslice(/*enet_time_get_sec()*/ time(NULL), 5); } } |
Modified src/serverbrowser.mm from [4bf1a6646d] to [7dc044a533].
︙ | ︙ | |||
32 33 34 35 36 37 38 | if (resolverqueries.empty()) { SDL_UnlockMutex(resolvermutex); continue; } rt->query = resolverqueries.pop(); rt->starttime = lastmillis; SDL_UnlockMutex(resolvermutex); | | < > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | if (resolverqueries.empty()) { SDL_UnlockMutex(resolvermutex); continue; } rt->query = resolverqueries.pop(); rt->starttime = lastmillis; SDL_UnlockMutex(resolvermutex); ENetAddress address = { ENET_HOST_ANY, CUBE_SERVINFO_PORT }; enet_address_set_host(&address, rt->query); SDL_LockMutex(resolvermutex); resolverresult &rr = resolverresults.add(); rr.query = rt->query; rr.address = address; rt->query = NULL; rt->starttime = 0; SDL_UnlockMutex(resolvermutex); } return 0; } void resolverinit(int threads, int limit) { resolverlimit = limit; |
︙ | ︙ | |||
121 122 123 124 125 126 127 | resolverthread &rt = resolverthreads[i]; if (rt.query) { if (lastmillis - rt.starttime > resolverlimit) { resolverstop(rt, true); *name = rt.query; SDL_UnlockMutex(resolvermutex); return true; | < < > > | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | resolverthread &rt = resolverthreads[i]; if (rt.query) { if (lastmillis - rt.starttime > resolverlimit) { resolverstop(rt, true); *name = rt.query; SDL_UnlockMutex(resolvermutex); return true; } } } SDL_UnlockMutex(resolvermutex); return false; } struct serverinfo { string name; |
︙ | ︙ | |||
195 196 197 198 199 200 201 | lastinfo = lastmillis; } void checkresolver() { char *name = NULL; | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | lastinfo = lastmillis; } void checkresolver() { char *name = NULL; ENetAddress addr = { ENET_HOST_ANY, CUBE_SERVINFO_PORT }; while (resolvercheck(&name, &addr)) { if (addr.host == ENET_HOST_ANY) continue; loopv(servers) { serverinfo &si = servers[i]; if (name == si.name) { |
︙ | ︙ | |||
301 302 303 304 305 306 307 | void servermenu() { if (pingsock == ENET_SOCKET_NULL) { pingsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM, NULL); resolverinit(1, 1000); | < > | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | void servermenu() { if (pingsock == ENET_SOCKET_NULL) { pingsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM, NULL); resolverinit(1, 1000); } resolverclear(); loopv(servers) resolverquery(servers[i].name); refreshservers(); menuset(1); } void |
︙ | ︙ |
Modified src/serverms.mm from [21c02ed323] to [1d1c1a8ddd].
︙ | ︙ | |||
42 43 44 45 46 47 48 | enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE; if (enet_socket_wait(mssock, &events, 0) >= 0 && events) { int len = enet_socket_receive(mssock, NULL, &buf, 1); if (len <= 0) { enet_socket_destroy(mssock); mssock = ENET_SOCKET_NULL; return; | < > < > | < | < > < > | 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 | enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE; if (enet_socket_wait(mssock, &events, 0) >= 0 && events) { int len = enet_socket_receive(mssock, NULL, &buf, 1); if (len <= 0) { enet_socket_destroy(mssock); mssock = ENET_SOCKET_NULL; return; } buf.data = ((char *)buf.data) + len; ((char *)buf.data)[0] = 0; buf.dataLength -= len; } } uchar * stripheader(uchar *b) { char *s = strstr((char *)b, "\n\r\n"); if (!s) s = strstr((char *)b, "\n\n"); return s ? (uchar *)s : b; } ENetAddress masterserver = { ENET_HOST_ANY, 80 }; int updmaster = 0; string masterbase; string masterpath; uchar masterrep[MAXTRANS]; ENetBuffer masterb; void updatemasterserver(int seconds) { // send alive signal to masterserver every hour of uptime if (seconds > updmaster) { sprintf_sd(path)("%sregister.do?action=add", masterpath); httpgetsend(masterserver, masterbase, path, "cubeserver", "Cube Server"); masterrep[0] = 0; masterb.data = masterrep; masterb.dataLength = MAXTRANS - 1; updmaster = seconds + 60 * 60; } } void checkmasterreply() { bool busy = mssock != ENET_SOCKET_NULL; httpgetrecieve(masterb); |
︙ | ︙ | |||
155 156 157 158 159 160 161 | if (!mid) mid = master; strcpy_s(masterpath, mid); strn0cpy(masterbase, master, mid - master + 1); serverdesc = sdesc; if (listen) { | | | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | if (!mid) mid = master; strcpy_s(masterpath, mid); strn0cpy(masterbase, master, mid - master + 1); serverdesc = sdesc; if (listen) { ENetAddress address = { ENET_HOST_ANY, CUBE_SERVINFO_PORT }; pongsock = enet_socket_create( ENET_SOCKET_TYPE_DATAGRAM, &address); if (pongsock == ENET_SOCKET_NULL) fatal(@"could not create server info socket\n"); } } } |
Modified src/serverutil.mm from [9a3fdd3f13] to [34361918f4].
︙ | ︙ | |||
16 17 18 19 20 21 22 | *p++ = n >> 8; } else { *p++ = 0x81; *p++ = n; *p++ = n >> 8; *p++ = n >> 16; *p++ = n >> 24; | < > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | *p++ = n >> 8; } else { *p++ = 0x81; *p++ = n; *p++ = n >> 8; *p++ = n >> 16; *p++ = n >> 24; } } int getint(uchar *&p) { int c = *((char *)p); p++; |
︙ | ︙ | |||
50 51 52 53 54 55 56 | while (*t) putint(p, *t++); putint(p, 0); } } static const OFString *modenames[] = { | | | | | | | | | | | | | | | < | < | | | | | | | > | 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 | while (*t) putint(p, *t++); putint(p, 0); } } static const OFString *modenames[] = { @"SP", @"DMSP", @"ffa/default", @"coopedit", @"ffa/duel", @"teamplay", @"instagib", @"instagib team", @"efficiency", @"efficiency team", @"insta arena", @"insta clan arena", @"tactics arena", @"tactics clan arena", }; OFString * modestr(int n) { return (n >= -2 && n < 12) ? modenames[n + 2] : @"unknown"; } // size inclusive message token, 0 for variable or not-checked sizes char msgsizesl[] = { SV_INITS2C, 4, SV_INITC2S, 0, SV_POS, 12, SV_TEXT, 0, SV_SOUND, 2, SV_CDIS, 2, SV_EDITH, 7, SV_EDITT, 7, SV_EDITS, 6, SV_EDITD, 6, SV_EDITE, 6, SV_DIED, 2, SV_DAMAGE, 4, SV_SHOT, 8, SV_FRAGS, 2, SV_MAPCHANGE, 0, SV_ITEMSPAWN, 2, SV_ITEMPICKUP, 3, SV_DENIED, 2, SV_PING, 2, SV_PONG, 2, SV_CLIENTPING, 2, SV_GAMEMODE, 2, SV_TIMEUP, 2, SV_EDITENT, 10, SV_MAPRELOAD, 2, SV_ITEMACC, 2, SV_SENDMAP, 0, SV_RECVMAP, 1, SV_SERVMSG, 0, SV_ITEMLIST, 0, SV_EXT, 0, -1 }; char msgsizelookup(int msg) { for (char *p = msgsizesl; *p >= 0; p += 2) if (*p == msg) return p[1]; |
︙ | ︙ | |||
183 184 185 186 187 188 189 | passwd = a; break; case 'c': maxcl = atoi(a); break; default: printf("WARNING: unknown commandline option\n"); | < < > > | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | passwd = a; break; case 'c': maxcl = atoi(a); break; default: printf("WARNING: unknown commandline option\n"); } } if (enet_initialize() < 0) fatal(@"Unable to initialise network module"); initserver(true, uprate, @(sdesc), @(ip), @(master), @(passwd), maxcl); return 0; } #endif |
Modified src/sound.mm from [af1eb7e101] to [7dfddc04de].
︙ | ︙ | |||
41 42 43 44 45 46 47 | #ifdef USE_MIXER Mix_HaltMusic(); Mix_FreeMusic(mod); #else FMUSIC_FreeSong(mod); #endif mod = NULL; | < > < > < > | 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 | #ifdef USE_MIXER Mix_HaltMusic(); Mix_FreeMusic(mod); #else FMUSIC_FreeSong(mod); #endif mod = NULL; } if (stream) { #ifndef USE_MIXER FSOUND_Stream_Close(stream); #endif stream = NULL; } } VAR(soundbufferlen, 128, 1024, 4096); void initsound() { memset(soundlocs, 0, sizeof(soundloc) * MAXCHAN); #ifdef USE_MIXER if (Mix_OpenAudio(SOUNDFREQ, MIX_DEFAULT_FORMAT, 2, soundbufferlen) < 0) { conoutf(@"sound init failed (SDL_mixer): %s", (size_t)Mix_GetError()); nosound = true; } Mix_AllocateChannels(MAXCHAN); #else if (FSOUND_GetVersion() < FMOD_VERSION) fatal(@"old FMOD dll"); if (!FSOUND_Init(SOUNDFREQ, MAXCHAN, FSOUND_INIT_GLOBALFOCUS)) { conoutf(@"sound init failed (FMOD): %d", FSOUND_GetError()); nosound = true; |
︙ | ︙ | |||
178 179 180 181 182 183 184 | float yaw = -atan2(v.x, v.y) - player1->yaw * (PI / 180.0f); // relative angle of // sound along X-Y axis pan = int(255.9f * (0.5 * sin(yaw) + 0.5f)); // range is from 0 (left) // to 255 (right) | < < > > | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | float yaw = -atan2(v.x, v.y) - player1->yaw * (PI / 180.0f); // relative angle of // sound along X-Y axis pan = int(255.9f * (0.5 * sin(yaw) + 0.5f)); // range is from 0 (left) // to 255 (right) } } vol = (vol * MAXVOL) / 255; #ifdef USE_MIXER Mix_Volume(chan, vol); Mix_SetPanning(chan, 255 - pan, pan); #else FSOUND_SetVolume(chan, vol); FSOUND_SetPan(chan, pan); |
︙ | ︙ |
Modified src/weapon.mm from [93de7b2cbf] to [a095df6286].
︙ | ︙ | |||
9 10 11 12 13 14 15 | static const int MONSTERDAMAGEFACTOR = 4; static const int SGRAYS = 20; static const float SGSPREAD = 2; static OFVector3D sg[SGRAYS]; static const guninfo guns[NUMGUNS] = { | | | | | | | | | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | static const int MONSTERDAMAGEFACTOR = 4; static const int SGRAYS = 20; static const float SGSPREAD = 2; static OFVector3D sg[SGRAYS]; static const guninfo guns[NUMGUNS] = { { S_PUNCH1, 250, 50, 0, 0, 1, @"fist" }, { S_SG, 1400, 10, 0, 0, 20, @"shotgun" }, // *SGRAYS { S_CG, 100, 30, 0, 0, 7, @"chaingun" }, { S_RLFIRE, 800, 120, 80, 0, 10, @"rocketlauncher" }, { S_RIFLE, 1500, 100, 0, 0, 30, @"rifle" }, { S_FLAUNCH, 200, 20, 50, 4, 1, @"fireball" }, { S_ICEBALL, 200, 40, 30, 6, 1, @"iceball" }, { S_SLIMEBALL, 200, 30, 160, 7, 1, @"slimeball" }, { S_PIGR1, 250, 50, 0, 0, 1, @"bite" }, }; void selectgun(int a, int b, int c) { if (a < -1 || b < -1 || c < -1 || a >= NUMGUNS || b >= NUMGUNS || c >= NUMGUNS) |
︙ | ︙ | |||
169 170 171 172 173 174 175 | if (d == player1) selfdamage(damage, at == player1 ? -1 : -2, at); else if (d->monsterstate) monsterpain(d, damage, at); else { addmsg(1, 4, SV_DAMAGE, target, damage, d->lifesequence); playsound(S_PAIN1 + rnd(5), &d->o); | < > | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | if (d == player1) selfdamage(damage, at == player1 ? -1 : -2, at); else if (d->monsterstate) monsterpain(d, damage, at); else { addmsg(1, 4, SV_DAMAGE, target, damage, d->lifesequence); playsound(S_PAIN1 + rnd(5), &d->o); } particle_splash(3, damage, 1000, d->o); demodamage(damage, d->o); } const float RL_RADIUS = 5; const float RL_DAMRAD = 7; // hack |
︙ | ︙ |
Modified src/world.mm from [50f4e28f8c] to [e205b06d1f].
︙ | ︙ | |||
21 22 23 24 25 26 27 | if (tag) { if (tag == s->tag) s->type = SPACE; else continue; } else { s->type = type ? SOLID : SPACE; | < > < | > | | 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 | if (tag) { if (tag == s->tag) s->type = SPACE; else continue; } else { s->type = type ? SOLID : SPACE; } if (x > maxx) maxx = x; if (y > maxy) maxy = y; if (x < minx) minx = x; if (y < miny) miny = y; } } block b = { minx, miny, maxx - minx + 1, maxy - miny + 1 }; if (maxx) remip(b); // remip minimal area of changed geometry } void resettagareas() { |
︙ | ︙ | |||
93 94 95 96 97 98 99 | sqr *v = wmip[level + 1]; int ws = ssize >> level; int vs = ssize >> (level + 1); block s = b; if (s.x & 1) { s.x--; s.xs++; | < > < > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | sqr *v = wmip[level + 1]; int ws = ssize >> level; int vs = ssize >> (level + 1); block s = b; if (s.x & 1) { s.x--; s.xs++; } if (s.y & 1) { s.y--; s.ys++; } s.xs = (s.xs + 1) & ~1; s.ys = (s.ys + 1) & ~1; for (int x = s.x; x < s.x + s.xs; x += 2) for (int y = s.y; y < s.y + s.ys; y += 2) { sqr *o[4]; o[0] = SWS(w, x, y, ws); // the 4 constituent cubes o[1] = SWS(w, x + 1, y, ws); |
︙ | ︙ | |||
140 141 142 143 144 145 146 | ch += o[i]->vdelta / 4 + 2; // FIXME: needs // to somehow // take into // account middle // vertices on // higher mips | < > < > | 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 | ch += o[i]->vdelta / 4 + 2; // FIXME: needs // to somehow // take into // account middle // vertices on // higher mips } if (fh < floor) floor = fh; // take lowest floor and // highest ceil, so we // never have to see // missing lower/upper // from the side if (ch > ceil) ceil = ch; } r->floor = floor; r->ceil = ceil; } if (r->type == CORNER) goto mip; // special case: don't ever split even // if textures etc are different r->defer = 1; if (SOLID(r)) { loopi(3) { |
︙ | ︙ | |||
214 215 216 217 218 219 220 | 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; | < < > > | | < > | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | 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; } } { loopi(4) if (o[i]->defer) goto c; } // if any of the constituents is not perfect, then // this one isn't either mip: r->defer = 0; c:; } s.x /= 2; s.y /= 2; s.xs /= 2; s.ys /= 2; remip(s, level + 1); } |
︙ | ︙ | |||
263 264 265 266 267 268 269 | if (e.type == NOTUSED) continue; OFVector3D v = OFMakeVector3D(e.x, e.y, e.z); vdist(dist, t, player1->o, v); if (dist < bdist) { best = i; bdist = dist; | < > | 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | if (e.type == NOTUSED) continue; OFVector3D v = OFMakeVector3D(e.x, e.y, e.z); vdist(dist, t, player1->o, v); if (dist < bdist) { best = i; bdist = dist; } } return bdist == 99999 ? -1 : best; } void entproperty(int prop, int amount) { |
︙ | ︙ | |||
287 288 289 290 291 292 293 | break; case 2: ents[e].attr3 += amount; break; case 3: ents[e].attr4 += amount; break; | < > | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | break; case 2: ents[e].attr3 += amount; break; case 3: ents[e].attr4 += amount; break; } } void delent() { int e = closestent(); if (e < 0) { |
︙ | ︙ | |||
322 323 324 325 326 327 328 | } } entity * newentity(int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4) { int type = findtype(what); | | | < > | 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 | } } entity * newentity(int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4) { int type = findtype(what); persistent_entity e = { (short)x, (short)y, (short)z, (short)v1, (uchar)type, (uchar)v2, (uchar)v3, (uchar)v4 }; switch (type) { case LIGHT: if (v1 > 32) v1 = 32; if (!v1) e.attr1 = 16; if (!v2 && !v3 && !v4) e.attr2 = 255; break; case MAPMODEL: e.attr4 = e.attr3; e.attr3 = e.attr2; case MONSTER: case TELEDEST: e.attr2 = (uchar)e.attr1; case PLAYERSTART: e.attr1 = (int)player1->yaw; break; } addmsg(1, 10, SV_EDITENT, ents.length(), type, e.x, e.y, e.z, e.attr1, e.attr2, e.attr3, e.attr4); ents.add(*((entity *)&e)); // unsafe! if (type == LIGHT) calclight(); return &ents.last(); } |
︙ | ︙ | |||
395 396 397 398 399 400 401 | e.attr1 = 2; if (e.attr1 > 32) e.attr1 = 32; if (intens) { scalecomp(e.attr2, intens); scalecomp(e.attr3, intens); scalecomp(e.attr4, intens); | < > | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | e.attr1 = 2; if (e.attr1 > 32) e.attr1 = 32; if (intens) { scalecomp(e.attr2, intens); scalecomp(e.attr3, intens); scalecomp(e.attr4, intens); } } calclight(); } COMMAND(scalelights, ARG_2INT) int findentity(int type, int index) |
︙ | ︙ | |||
441 442 443 444 445 446 447 | cleardlights(); pruneundos(); sqr *oldworld = world; bool copy = false; if (oldworld && factor < 0) { factor = sfactor + 1; copy = true; | < > | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 | cleardlights(); pruneundos(); sqr *oldworld = world; bool copy = false; if (oldworld && factor < 0) { factor = sfactor + 1; copy = true; } if (factor < SMALLEST_FACTOR) factor = SMALLEST_FACTOR; if (factor > LARGEST_FACTOR) factor = LARGEST_FACTOR; setupworld(factor); loop(x, ssize) loop(y, ssize) |
︙ | ︙ | |||
484 485 486 487 488 489 490 | } } else { strn0cpy(hdr.maptitle, "Untitled Map by Unknown", 128); hdr.waterlevel = -100000; loopi(15) hdr.reserved[i] = 0; loopk(3) loopi(256) hdr.texlists[k][i] = i; ents.setsize(0); | | | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 | } } else { strn0cpy(hdr.maptitle, "Untitled Map by Unknown", 128); hdr.waterlevel = -100000; loopi(15) hdr.reserved[i] = 0; loopk(3) loopi(256) hdr.texlists[k][i] = i; ents.setsize(0); block b = { 8, 8, ssize - 16, ssize - 16 }; edittypexy(SPACE, b); } calclight(); startmap(@"base/unnamed"); if (oldworld) { free(oldworld); |
︙ | ︙ |
Modified src/worldlight.mm from [3bb65afc34] to [2af1475366].
︙ | ︙ | |||
95 96 97 98 99 100 101 | if (SOLID(s)) return; x += stepx; y += stepy; l -= stepl; stepl -= 25; } | < > < > < > < > | 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 137 138 139 140 141 142 143 144 145 146 147 148 | if (SOLID(s)) return; x += stepx; y += stepy; l -= stepl; stepl -= 25; } } } else // the old (white) light code, here for the few people with old // video cards that don't support overbright { loopi(steps) { sqr *s = S(x >> PRECBITS, y >> PRECBITS); int light = l >> PRECBITS; if (light > s->r) s->r = s->g = s->b = (uchar)light; if (SOLID(s)) return; x += stepx; y += stepy; l -= stepl; } } } void calclightsource(persistent_entity &l) { int reach = l.attr1; int sx = l.x - reach; int ex = l.x + reach; int sy = l.y - reach; int ey = l.y + reach; rndreset(); const float s = 0.8f; for (float sx2 = (float)sx; sx2 <= ex; sx2 += s * 2) { lightray(sx2, (float)sy, l); lightray(sx2, (float)ey, l); } for (float sy2 = sy + s; sy2 <= ey - s; sy2 += s * 2) { lightray((float)sx, sy2, l); lightray((float)ex, sy2, l); } rndtime(); } void postlightarea(block &a) // median filter, smooths out random noise in light and // makes it more mipable |
︙ | ︙ | |||
176 177 178 179 180 181 182 | loopv(ents) { entity &e = ents[i]; if (e.type == LIGHT) calclightsource(e); } | | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | loopv(ents) { entity &e = ents[i]; if (e.type == LIGHT) calclightsource(e); } block b = { 1, 1, ssize - 2, ssize - 2 }; postlightarea(b); setvar(@"fullbright", 0); } VARP(dynlight, 0, 16, 32); vector<block *> dlights; |
︙ | ︙ | |||
209 210 211 212 213 214 215 | reach = reach / 2; if (!reach) return; if (v.x < 0 || v.y < 0 || v.x > ssize || v.y > ssize) return; int creach = reach + 16; // dependant on lightray random offsets! | | | | | | 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 | reach = reach / 2; if (!reach) return; if (v.x < 0 || v.y < 0 || v.x > ssize || v.y > ssize) return; int creach = reach + 16; // dependant on lightray random offsets! block b = { (int)v.x - creach, (int)v.y - creach, creach * 2 + 1, creach * 2 + 1 }; if (b.x < 1) b.x = 1; if (b.y < 1) b.y = 1; if (b.xs + b.x > ssize - 2) b.xs = ssize - 2 - b.x; if (b.ys + b.y > ssize - 2) b.ys = ssize - 2 - b.y; dlights.add(blockcopy(b)); // backup area before rendering in dynlight persistent_entity l = { (short)v.x, (short)v.y, (short)v.z, (short)reach, LIGHT, (uchar)strength, 0, 0 }; calclightsource(l); postlightarea(b); } // utility functions also used by editing code block * |
︙ | ︙ |
Modified src/worldocull.mm from [7b61604ca1] to [fabee6f557].
︙ | ︙ | |||
53 54 55 56 57 58 59 | dy = -(ray - 4); } else if (ray >= 5 && ray < 7) { dx = ray - 6; dy = -1; } else { dx = 1; dy = ray > 4 ? ray - 8 : ray; | < > < < | | < > < < > > | < | 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 | 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 if (SOLID(S(fast_f2nat(sx), fast_f2nat(sy)))) { rdist[i] = (float)(fabs(sx - vx) + fabs(sy - vy)); break; } } } else rdist[i] = 2; } } // test occlusion for a cube... one of the most computationally expensive // functions in the engine as its done for every cube and entity, but its effect // is more than worth it! |
︙ | ︙ | |||
148 149 150 151 152 153 154 | 4; l = ma(-(cx + csize - vx), -(cy - vy)) + 4; } // D } else { h = ca(cy + csize - vy, -(cx + csize - vx)) + 2; l = ca(cy - vy, -(cx - vx)) + 2; | | | < | < > | | < > | | | < > | 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 | 4; l = ma(-(cx + csize - vx), -(cy - vy)) + 4; } // D } else { h = ca(cy + csize - vy, -(cx + csize - vx)) + 2; l = ca(cy - vy, -(cx - vx)) + 2; } // F } else { // BG if (cy <= vy) { if (cy + csize < vy) { h = ma(-(cy + csize - vy), cx - vx) + 6; l = ma(-(cy + csize - vy), cx + csize - vx) + 6; } // B else return 0; } else { h = ma(cy - vy, -(cx + csize - vx)) + 2; l = ma(cy - vy, -(cx - vx)) + 2; } // G } } else // CEH { if (cy <= vy) // CE { if (cy + csize < vy) { h = ca(-(cy - vy), cx - vx) + 6; l = ca(-(cy + csize - vy), cx + csize - vx) + 6; } // C else { h = ma(cx - vx, cy - vy); l = ma(cx - vx, cy + csize - vy); } // E } else { h = ca(cx + csize - vx, cy - vy); l = ca(cx - vx, cy + csize - vy); } // H } int si = fast_f2nat(h * (NUMRAYS / 8)) + NUMRAYS; // get indexes into occlusion map from angles int ei = fast_f2nat(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.mm from [5690f47554] to [b1342f3226].
︙ | ︙ | |||
10 11 12 13 14 15 16 | { if (SOLID(o) || o->type == SEMISOLID) { float c1 = s->floor; float c2 = s->floor; if (s->type == FHF) { c1 -= d1->vdelta / 4.0f; c2 -= d2->vdelta / 4.0f; | < > < > < > < > < > | 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 | { if (SOLID(o) || o->type == SEMISOLID) { float c1 = s->floor; float c2 = s->floor; if (s->type == FHF) { c1 -= d1->vdelta / 4.0f; c2 -= d2->vdelta / 4.0f; } float f1 = s->ceil; float f2 = s->ceil; if (s->type == CHF) { f1 += d1->vdelta / 4.0f; f2 += d2->vdelta / 4.0f; } // if(f1-c1<=0 && f2-c2<=0) return; render_square(o->wtex, c1, c2, f1, f2, x1 << mip, y1 << mip, x2 << mip, y2 << mip, 1 << mip, d1, d2, topleft); return; } { float f1 = s->floor; float f2 = s->floor; float c1 = o->floor; float c2 = o->floor; if (o->type == FHF && s->type != FHF) { c1 -= d1->vdelta / 4.0f; c2 -= d2->vdelta / 4.0f; } if (s->type == FHF && o->type != FHF) { f1 -= d1->vdelta / 4.0f; f2 -= d2->vdelta / 4.0f; } if (f1 >= c1 && f2 >= c2) goto skip; render_square(o->wtex, f1, f2, c1, c2, x1 << mip, y1 << mip, x2 << mip, y2 << mip, 1 << mip, d1, d2, topleft); } skip: { float f1 = o->ceil; float f2 = o->ceil; float c1 = s->ceil; float c2 = s->ceil; if (o->type == CHF && s->type != CHF) { f1 += d1->vdelta / 4.0f; f2 += d2->vdelta / 4.0f; } else if (s->type == CHF && o->type != CHF) { c1 += d1->vdelta / 4.0f; c2 += d2->vdelta / 4.0f; } if (c1 <= f1 && c2 <= f2) return; render_square(o->utex, f1, f2, c1, c2, x1 << mip, y1 << mip, x2 << mip, y2 << mip, 1 << mip, d1, d2, topleft); } } const int MAX_MIP = 5; // 32x32 unit blocks const int MIN_LOD = 2; const int LOW_LOD = 25; const int MAX_LOD = 1000; |
︙ | ︙ | |||
90 91 92 93 94 95 96 | if (issemi(mip, x + x1, y + y1, x1, y1, x2, y2)) return true; case CORNER: case SOLID: break; default: return true; | < > < > | 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 | if (issemi(mip, x + x1, y + y1, x1, y1, x2, y2)) return true; case CORNER: case SOLID: break; default: return true; } switch (SWS(w, x + x2, y + y2, msize)->type) { case SEMISOLID: if (issemi(mip, x + x2, y + y2, x1, y1, x2, y2)) return true; case CORNER: case SOLID: break; default: return true; } return false; } bool render_floor, render_ceil; // the core recursive function, renders a rect of cubes at a certain mip level // from a viewer perspective call itself for lower mip levels, on most modern |
︙ | ︙ | |||
127 128 129 130 131 132 133 | vxx - lodleft; // these mark the rect inside the current rest that // we want to render using a lower mip level int ly = vyy - lodtop; int rx = vxx + lodright; int ry = vyy + lodbot; float fsize = (float)(1 << mip); | | < | < > < > > < > | 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 | vxx - lodleft; // these mark the rect inside the current rest that // we want to render using a lower mip level int ly = vyy - lodtop; int rx = vxx + lodright; int ry = vyy + lodbot; float fsize = (float)(1 << mip); 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->o.x, player1->o.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; SWS(w, pvx, pvy, sz)->occluded = 0; // player cell never occluded } #define df(x) s->floor - (x->vdelta / 4.0f) #define dc(x) s->ceil + (x->vdelta / 4.0f) // 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 |
︙ | ︙ | |||
191 192 193 194 195 196 197 | render_flat(s->ctex, xx << mip, yy << mip, 1 << mip, s->ceil, s, t, u, v, true); if (s->type == CHF) // if(s->ceil>=vh) render_flatdelta(s->ctex, xx << mip, yy << mip, 1 << mip, dc(s), dc(t), dc(u), dc(v), s, t, u, v, true); } } | < < > < < > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | render_flat(s->ctex, xx << mip, yy << mip, 1 << mip, s->ceil, s, t, u, v, true); if (s->type == CHF) // if(s->ceil>=vh) render_flatdelta(s->ctex, xx << mip, yy << mip, 1 << mip, dc(s), dc(t), dc(u), dc(v), s, t, u, v, true); } } LOOPH continue; // floors LOOPD if ((s->type == SPACE || s->type == CHF) && s->floor <= vh && render_floor) { render_flat(s->ftex, xx << mip, yy << mip, 1 << mip, s->floor, s, t, u, v, false); if (s->floor < hdr.waterlevel && !SOLID(s)) addwaterquad(xx << mip, yy << mip, 1 << mip); } if (s->type == FHF) { render_flatdelta(s->ftex, xx << mip, yy << mip, 1 << mip, df(s), df(t), df(u), df(v), s, t, u, v, false); if (s->floor - s->vdelta / 4.0f < hdr.waterlevel && !SOLID(s)) addwaterquad(xx << mip, yy << mip, 1 << mip); } } } LOOPH continue; // walls LOOPD // w // zSt // vu |
︙ | ︙ | |||
234 235 236 237 238 239 240 | if (SOLID(w)) { render_wall(w, h2 = s, xx + 1, yy, xx, yy + 1, mip, t, v, false); topleft = false; } else if (SOLID(v)) { render_wall(v, h2 = s, xx, yy, xx + 1, yy + 1, mip, s, u, false); | < > < > < > < < < > > > | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 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 | if (SOLID(w)) { render_wall(w, h2 = s, xx + 1, yy, xx, yy + 1, mip, t, v, false); topleft = false; } else if (SOLID(v)) { render_wall(v, h2 = s, xx, yy, xx + 1, yy + 1, mip, s, u, false); } } else if (SOLID(t)) { if (SOLID(w)) { render_wall(w, h1 = s, xx + 1, yy + 1, xx, yy, mip, u, s, false); } else if (SOLID(v)) { render_wall(v, h1 = s, xx, yy + 1, xx + 1, yy, mip, v, t, false); topleft = false; } } else { normalwall = false; bool wv = w->ceil - w->floor < v->ceil - v->floor; if (z->ceil - z->floor < t->ceil - t->floor) { if (wv) { render_wall(h1 = s, h2 = v, xx + 1, yy, xx, yy + 1, mip, t, v, false); topleft = false; } else { render_wall(h1 = s, h2 = w, xx, yy, xx + 1, yy + 1, mip, s, u, false); } } else { if (wv) { render_wall(h2 = s, h1 = v, xx + 1, yy + 1, xx, yy, mip, u, s, false); } else { render_wall(h2 = s, h1 = w, xx, yy + 1, xx + 1, yy, mip, v, t, false); topleft = false; } } } render_tris( xx << mip, yy << mip, 1 << mip, topleft, h1, h2, s, t, u, v); } if (normalwall) { bool inner = xx != sz - 1 && yy != sz - 1; |
︙ | ︙ | |||
290 291 292 293 294 295 296 | (!SOLID(s) || w->type != CORNER) && (w->type != SEMISOLID || issemi(mip, xx, yy - 1, 0, 1, 1, 1))) render_wall(s, w, xx, yy, xx + 1, yy, mip, s, t, false); if (yy <= vyy && inner && !SOLID(v) && (!SOLID(s) || v->type != CORNER) && (v->type != SEMISOLID || issemi(mip, xx, yy + 1, 0, 0, 1, 0))) render_wall(s, v, xx, yy + 1, xx + 1, yy + 1, mip, v, u, true); | < < < > | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | (!SOLID(s) || w->type != CORNER) && (w->type != SEMISOLID || issemi(mip, xx, yy - 1, 0, 1, 1, 1))) render_wall(s, w, xx, yy, xx + 1, yy, mip, s, t, false); if (yy <= vyy && inner && !SOLID(v) && (!SOLID(s) || v->type != CORNER) && (v->type != SEMISOLID || issemi(mip, xx, yy + 1, 0, 0, 1, 0))) render_wall(s, v, xx, yy + 1, xx + 1, yy + 1, mip, v, u, true); } } } } void distlod(int &low, int &high, int angle, float widef) { float f = 90.0f / lod / widef; low = (int)((90 - angle) / f); high = (int)(angle / f); |
︙ | ︙ | |||
321 322 323 324 325 326 327 | float vx, float vy, float vh, int yaw, int pitch, float fov, int w, int h) { loopi(LARGEST_FACTOR) stats[i] = 0; min_lod = MIN_LOD + abs(pitch) / 12; yaw = 360 - yaw; float widef = fov / 75.0f; int cdist = abs(yaw % 90 - 45); | | < > > | < | < < > < > | 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 | float vx, float vy, float vh, int yaw, int pitch, float fov, int w, int h) { loopi(LARGEST_FACTOR) stats[i] = 0; min_lod = MIN_LOD + abs(pitch) / 12; yaw = 360 - yaw; float widef = fov / 75.0f; int cdist = abs(yaw % 90 - 45); // hack to avoid popup at high fovs at 45 yaw if (cdist < 7) { // less if lod worked better min_lod = max(min_lod, (int)(MIN_LOD + (10 - cdist) / 1.0f * widef)); widef = 1.0f; } lod = MAX_LOD; lodtop = lodbot = lodleft = lodright = min_lod; if (yaw > 45 && yaw <= 135) { lodleft = lod; distlod(lodtop, lodbot, yaw - 45, widef); } else if (yaw > 135 && yaw <= 225) { lodbot = lod; distlod(lodleft, lodright, yaw - 135, widef); } else if (yaw > 225 && yaw <= 315) { lodright = lod; distlod(lodbot, lodtop, yaw - 225, widef); } else { lodtop = lod; distlod( lodright, lodleft, yaw <= 45 ? yaw + 45 : yaw - 315, widef); } float hyfov = fov * h / w / 2; render_floor = pitch < hyfov; render_ceil = -pitch < hyfov; render_seg_new( vx, vy, vh, MAX_MIP, 0, 0, ssize >> MAX_MIP, ssize >> MAX_MIP); mipstats(stats[0], stats[1], stats[2]); } |