├── common ├── test.h ├── threads.h ├── trilib.h ├── scriplib.h ├── polylib.h ├── lbmlib.h ├── wadlib.h ├── mathlib.h ├── mathlib.c ├── cmdlib.h ├── scriplib.c ├── common.vcxproj ├── trilib.c ├── threads.c ├── bspfile.h ├── wadlib.c └── polylib.c ├── xcode ├── light │ ├── light │ │ └── .gitignore │ └── light.xcodeproj │ │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── fabiensanglard.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ └── fabiensanglard.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── light.xcscheme ├── qbsp │ └── qbsp │ │ └── .gitignore ├── qcc │ ├── qcc │ │ └── .gitignore │ └── qcc.xcodeproj │ │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── fabiensanglard.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ └── fabiensanglard.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── qcc.xcscheme └── vis │ └── vis │ └── .gitignore ├── qc ├── progs.src ├── sprites.qc ├── progdefs.h ├── spectate.qc ├── server.qc ├── buttons.qc ├── subs.qc ├── combat.qc └── plats.qc ├── README ├── light ├── threads.h ├── entities.h ├── light.h ├── threads.c ├── light.c ├── light.vcxproj ├── trace.c └── entities.c ├── qbsp ├── nodraw.c ├── map.h ├── qbsp.vcxproj ├── outside.c ├── merge.c └── bsp5.h ├── qbsp.sln ├── maps └── simple.map ├── vis ├── vis.h ├── soundpvs.c └── vis.vcxproj ├── qcc ├── pr_comp.h └── qcc.vcxproj └── comments └── text.txt /common/test.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /xcode/light/light/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /xcode/qbsp/qbsp/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /xcode/qcc/qcc/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /xcode/vis/vis/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /xcode/qcc/qcc.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /xcode/light/light.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /qc/progs.src: -------------------------------------------------------------------------------- 1 | ./qwprogs.dat 2 | 3 | defs.qc 4 | subs.qc 5 | combat.qc 6 | items.qc 7 | weapons.qc 8 | world.qc 9 | client.qc 10 | spectate.qc 11 | player.qc 12 | doors.qc 13 | buttons.qc 14 | triggers.qc 15 | plats.qc 16 | misc.qc 17 | 18 | server.qc 19 | -------------------------------------------------------------------------------- /xcode/qcc/qcc.xcodeproj/project.xcworkspace/xcuserdata/fabiensanglard.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiensanglard/Quake--QBSP-and-VIS/HEAD/xcode/qcc/qcc.xcodeproj/project.xcworkspace/xcuserdata/fabiensanglard.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /xcode/light/light.xcodeproj/project.xcworkspace/xcuserdata/fabiensanglard.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiensanglard/Quake--QBSP-and-VIS/HEAD/xcode/light/light.xcodeproj/project.xcworkspace/xcuserdata/fabiensanglard.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is the source code of qbsp and vis: Quake preprocessing tools. 2 | 3 | They have been modified in order to trace the portal building system 4 | and the PVS building systems. 5 | 6 | Quake 1 maps have been released as GPL by John Romero on October 12, 2006 (In honour of Quake's 10th year). 7 | 8 | You can also use Q3Radiant: It features a built-in viewprt Portal Viewer that work on Quake1 files. 9 | 10 | -------------------------------------------------------------------------------- /xcode/qcc/qcc.xcodeproj/xcuserdata/fabiensanglard.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | qcc.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2DF5071F14C8DF20000A6C0D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /xcode/light/light.xcodeproj/xcuserdata/fabiensanglard.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | light.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2DF506CD14C8DDC3000A6C0D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /common/threads.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | extern int numthreads; 22 | 23 | int GetThreadWork (void); 24 | void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)); 25 | void ThreadLock (void); 26 | void ThreadUnlock (void); 27 | 28 | -------------------------------------------------------------------------------- /common/trilib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // 21 | // trilib.h: header file for loading triangles from an Alias triangle file 22 | // 23 | #define MAXTRIANGLES 2048 24 | 25 | typedef struct { 26 | vec3_t verts[3]; 27 | } triangle_t; 28 | 29 | void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles); 30 | 31 | -------------------------------------------------------------------------------- /light/threads.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | #ifdef __alpha 22 | #include 23 | extern pthread_mutex_t *my_mutex; 24 | #define LOCK pthread_mutex_lock (my_mutex) 25 | #define UNLOCK pthread_mutex_unlock (my_mutex) 26 | #else 27 | #define LOCK 28 | #define UNLOCK 29 | #endif 30 | 31 | extern int numthreads; 32 | 33 | typedef void (threadfunc_t) (void *); 34 | 35 | void InitThreads (void); 36 | void RunThreadsOn ( threadfunc_t func ); 37 | -------------------------------------------------------------------------------- /common/scriplib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // scriplib.h 21 | 22 | #ifndef __CMDLIB__ 23 | #include "cmdlib.h" 24 | #endif 25 | 26 | #define MAXTOKEN 128 27 | 28 | extern char token[MAXTOKEN]; 29 | extern char *scriptbuffer,*script_p,*scriptend_p; 30 | extern int grabbed; 31 | extern int scriptline; 32 | extern qboolean endofscript; 33 | 34 | 35 | void LoadScriptFile (char *filename); 36 | qboolean GetToken (qboolean crossline); 37 | void UnGetToken (void); 38 | qboolean TokenAvailable (void); 39 | 40 | 41 | -------------------------------------------------------------------------------- /qc/sprites.qc: -------------------------------------------------------------------------------- 1 | /* 2 | sprites.qc 3 | 4 | sprite definitions 5 | 6 | Copyright (C) 1996-1997 Id Software, Inc. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 | 17 | See the GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to: 21 | 22 | Free Software Foundation, Inc. 23 | 59 Temple Place - Suite 330 24 | Boston, MA 02111-1307, USA 25 | 26 | */ 27 | 28 | // these are the only sprites still in the game... 29 | 30 | $spritename s_explod 31 | $type vp_parallel 32 | $load /raid/quake/id1/gfx/sprites/explod03.lbm 33 | $frame 24 24 56 56 34 | $frame 120 24 56 56 35 | $frame 216 24 56 56 36 | $frame 24 88 56 56 37 | $frame 120 88 56 56 38 | $frame 216 88 56 56 39 | 40 | 41 | $spritename s_bubble 42 | $type vp_parallel 43 | $load /raid/quake/id1/gfx/sprites/bubble.lbm 44 | $frame 16 16 16 16 45 | $frame 40 16 16 16 46 | 47 | 48 | $spritename s_light 49 | $type vp_parallel 50 | $load /raid/quake/id1/gfx/sprites/light.lbm 51 | $frame 104 32 32 32 52 | 53 | -------------------------------------------------------------------------------- /qbsp/nodraw.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | #include "bsp5.h" 22 | 23 | void Draw_ClearBounds (void) 24 | { 25 | } 26 | 27 | void Draw_AddToBounds (vec3_t v) 28 | { 29 | } 30 | 31 | void Draw_DrawFace (face_t *f) 32 | { 33 | } 34 | 35 | void Draw_ClearWindow (void) 36 | { 37 | } 38 | 39 | void Draw_SetRed (void) 40 | { 41 | } 42 | 43 | void Draw_SetGrey (void) 44 | { 45 | } 46 | 47 | void Draw_SetBlack (void) 48 | { 49 | } 50 | 51 | void DrawPoint (vec3_t v) 52 | { 53 | } 54 | 55 | void DrawLeaf (node_t *l, int color) 56 | { 57 | } 58 | 59 | void DrawBrush (brush_t *b) 60 | { 61 | } 62 | 63 | void DrawWinding (winding_t *w) 64 | { 65 | } 66 | 67 | void DrawTri (vec3_t p1, vec3_t p2, vec3_t p3) 68 | { 69 | } 70 | 71 | void DrawPortal (portal_t *portal) 72 | { 73 | } 74 | -------------------------------------------------------------------------------- /common/polylib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | typedef struct 22 | { 23 | int numpoints; 24 | vec3_t p[4]; // variable sized 25 | } winding_t; 26 | 27 | #define MAX_POINTS_ON_WINDING 64 28 | 29 | #define ON_EPSILON 0.1 30 | 31 | winding_t *AllocWinding (int points); 32 | vec_t WindingArea (winding_t *w); 33 | void WindingCenter (winding_t *w, vec3_t center); 34 | void ClipWinding (winding_t *in, vec3_t normal, vec_t dist, 35 | winding_t **front, winding_t **back); 36 | winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist); 37 | winding_t *CopyWinding (winding_t *w); 38 | winding_t *BaseWindingForPlane (vec3_t normal, float dist); 39 | void CheckWinding (winding_t *w); 40 | void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist); 41 | void RemoveColinearPoints (winding_t *w); 42 | -------------------------------------------------------------------------------- /common/lbmlib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // lbmlib.h 21 | 22 | typedef unsigned char UBYTE; 23 | typedef short WORD; 24 | typedef unsigned short UWORD; 25 | typedef long LONG; 26 | 27 | typedef enum 28 | { 29 | ms_none, 30 | ms_mask, 31 | ms_transcolor, 32 | ms_lasso 33 | } mask_t; 34 | 35 | typedef enum 36 | { 37 | cm_none, 38 | cm_rle1 39 | } compress_t; 40 | 41 | typedef struct 42 | { 43 | UWORD w,h; 44 | WORD x,y; 45 | UBYTE nPlanes; 46 | UBYTE masking; 47 | UBYTE compression; 48 | UBYTE pad1; 49 | UWORD transparentColor; 50 | UBYTE xAspect,yAspect; 51 | WORD pageWidth,pageHeight; 52 | } bmhd_t; 53 | 54 | extern bmhd_t bmhd; // will be in native byte order 55 | 56 | 57 | void LoadLBM (char *filename, byte **picture, byte **palette); 58 | 59 | void WriteLBMfile (char *filename, byte *data, int width, int height 60 | , byte *palette); 61 | 62 | -------------------------------------------------------------------------------- /light/entities.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | #define DEFAULTLIGHTLEVEL 300 22 | 23 | typedef struct epair_s 24 | { 25 | struct epair_s *next; 26 | char key[MAX_KEY]; 27 | char value[MAX_VALUE]; 28 | } epair_t; 29 | 30 | typedef struct entity_s 31 | { 32 | char classname[64]; 33 | vec3_t origin; 34 | float angle; 35 | int light; 36 | int style; 37 | char target[32]; 38 | char targetname[32]; 39 | struct epair_s *epairs; 40 | struct entity_s *targetent; 41 | } entity_t; 42 | 43 | extern entity_t entities[MAX_MAP_ENTITIES]; 44 | extern int num_entities; 45 | 46 | char *ValueForKey (entity_t *ent, char *key); 47 | void SetKeyValue (entity_t *ent, char *key, char *value); 48 | float FloatForKey (entity_t *ent, char *key); 49 | void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); 50 | 51 | void LoadEntities (void); 52 | void WriteEntitiesToString (void); 53 | -------------------------------------------------------------------------------- /light/light.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | #include "cmdlib.h" 22 | #include "mathlib.h" 23 | #include "bspfile.h" 24 | #include "entities.h" 25 | #include "threads.h" 26 | 27 | #define ON_EPSILON 0.1 28 | 29 | #define MAXLIGHTS 1024 30 | 31 | void LoadNodes (char *file); 32 | qboolean TestLine (vec3_t start, vec3_t stop); 33 | 34 | void LightFace (int surfnum); 35 | void LightLeaf (dleaf_t *leaf); 36 | 37 | void MakeTnodes (dmodel_t *bm); 38 | 39 | extern float scaledist; 40 | extern float scalecos; 41 | extern float rangescale; 42 | 43 | extern int c_culldistplane, c_proper; 44 | 45 | byte *GetFileSpace (int size); 46 | extern byte *filebase; 47 | 48 | extern vec3_t bsp_origin; 49 | extern vec3_t bsp_xvector; 50 | extern vec3_t bsp_yvector; 51 | 52 | void TransformSample (vec3_t in, vec3_t out); 53 | void RotateSample (vec3_t in, vec3_t out); 54 | 55 | extern qboolean extrasamples; 56 | 57 | extern float minlights[MAX_MAP_FACES]; 58 | -------------------------------------------------------------------------------- /qbsp/map.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | 22 | #define MAX_FACES 16 23 | typedef struct mface_s 24 | { 25 | struct mface_s *next; 26 | plane_t plane; 27 | int texinfo; 28 | } mface_t; 29 | 30 | typedef struct mbrush_s 31 | { 32 | struct mbrush_s *next; 33 | mface_t *faces; 34 | } mbrush_t; 35 | 36 | typedef struct epair_s 37 | { 38 | struct epair_s *next; 39 | char *key; 40 | char *value; 41 | } epair_t; 42 | 43 | typedef struct 44 | { 45 | vec3_t origin; 46 | mbrush_t *brushes; 47 | epair_t *epairs; 48 | } entity_t; 49 | 50 | extern int nummapbrushes; 51 | extern mbrush_t mapbrushes[MAX_MAP_BRUSHES]; 52 | 53 | extern int num_entities; 54 | extern entity_t entities[MAX_MAP_ENTITIES]; 55 | 56 | extern int nummiptex; 57 | extern char miptex[MAX_MAP_TEXINFO][16]; 58 | 59 | void LoadMapFile (char *filename); 60 | 61 | int FindMiptex (char *name); 62 | 63 | void PrintEntity (entity_t *ent); 64 | char *ValueForKey (entity_t *ent, char *key); 65 | void SetKeyValue (entity_t *ent, char *key, char *value); 66 | float FloatForKey (entity_t *ent, char *key); 67 | void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); 68 | 69 | void WriteEntitiesToString (void); 70 | -------------------------------------------------------------------------------- /common/wadlib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // wadlib.h 21 | 22 | // 23 | // wad reading 24 | // 25 | 26 | #define CMP_NONE 0 27 | #define CMP_LZSS 1 28 | 29 | #define TYP_NONE 0 30 | #define TYP_LABEL 1 31 | #define TYP_LUMPY 64 // 64 + grab command number 32 | 33 | typedef struct 34 | { 35 | char identification[4]; // should be WAD2 or 2DAW 36 | int numlumps; 37 | int infotableofs; 38 | } wadinfo_t; 39 | 40 | 41 | typedef struct 42 | { 43 | int filepos; 44 | int disksize; 45 | int size; // uncompressed 46 | char type; 47 | char compression; 48 | char pad1, pad2; 49 | char name[16]; // must be null terminated 50 | } lumpinfo_t; 51 | 52 | extern lumpinfo_t *lumpinfo; // location of each lump on disk 53 | extern int numlumps; 54 | extern wadinfo_t header; 55 | 56 | void W_OpenWad (char *filename); 57 | int W_CheckNumForName (char *name); 58 | int W_GetNumForName (char *name); 59 | int W_LumpLength (int lump); 60 | void W_ReadLumpNum (int lump, void *dest); 61 | void *W_LoadLumpNum (int lump); 62 | void *W_LoadLumpName (char *name); 63 | 64 | void CleanupName (char *in, char *out); 65 | 66 | // 67 | // wad creation 68 | // 69 | void NewWad (char *pathname, qboolean bigendien); 70 | void AddLump (char *name, void *buffer, int length, int type, int compress); 71 | void WriteWad (void); 72 | 73 | -------------------------------------------------------------------------------- /common/mathlib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | #ifndef __MATHLIB__ 21 | #define __MATHLIB__ 22 | 23 | // mathlib.h 24 | 25 | #include 26 | 27 | #ifdef DOUBLEVEC_T 28 | typedef double vec_t; 29 | #else 30 | typedef float vec_t; 31 | #endif 32 | typedef vec_t vec3_t[3]; 33 | 34 | #define SIDE_FRONT 0 35 | #define SIDE_ON 2 36 | #define SIDE_BACK 1 37 | #define SIDE_CROSS -2 38 | 39 | #define Q_PI 3.14159265358979323846 40 | 41 | extern vec3_t vec3_origin; 42 | 43 | #define EQUAL_EPSILON 0.001 44 | 45 | qboolean VectorCompare (vec3_t v1, vec3_t v2); 46 | 47 | #define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) 48 | #define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];} 49 | #define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];} 50 | #define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];} 51 | 52 | vec_t Q_rint (vec_t in); 53 | vec_t _DotProduct (vec3_t v1, vec3_t v2); 54 | void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out); 55 | void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out); 56 | void _VectorCopy (vec3_t in, vec3_t out); 57 | 58 | double VectorLength(vec3_t v); 59 | 60 | void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc); 61 | 62 | void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross); 63 | vec_t VectorNormalize (vec3_t v); 64 | void VectorInverse (vec3_t v); 65 | void VectorScale (vec3_t v, vec_t scale, vec3_t out); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /light/threads.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | #include "cmdlib.h" 22 | #include "threads.h" 23 | 24 | #ifdef __alpha 25 | int numthreads = 4; 26 | pthread_mutex_t *my_mutex; 27 | #else 28 | int numthreads = 1; 29 | #endif 30 | 31 | void InitThreads (void) 32 | { 33 | #ifdef __alpha 34 | pthread_mutexattr_t mattrib; 35 | 36 | my_mutex = malloc (sizeof(*my_mutex)); 37 | if (pthread_mutexattr_create (&mattrib) == -1) 38 | Error ("pthread_mutex_attr_create failed"); 39 | if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) 40 | Error ("pthread_mutexattr_setkind_np failed"); 41 | if (pthread_mutex_init (my_mutex, mattrib) == -1) 42 | Error ("pthread_mutex_init failed"); 43 | #endif 44 | } 45 | 46 | /* 47 | =============== 48 | RunThreadsOn 49 | =============== 50 | */ 51 | void RunThreadsOn ( threadfunc_t func ) 52 | { 53 | #ifdef __alpha 54 | pthread_t work_threads[256]; 55 | pthread_addr_t status; 56 | pthread_attr_t attrib; 57 | int i; 58 | 59 | if (numthreads == 1) 60 | { 61 | func (NULL); 62 | return; 63 | } 64 | 65 | if (pthread_attr_create (&attrib) == -1) 66 | Error ("pthread_attr_create failed"); 67 | if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) 68 | Error ("pthread_attr_setstacksize failed"); 69 | 70 | for (i=0 ; i EQUAL_EPSILON) 47 | return false; 48 | 49 | return true; 50 | } 51 | 52 | vec_t Q_rint (vec_t in) 53 | { 54 | return floor (in + 0.5); 55 | } 56 | 57 | void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc) 58 | { 59 | vc[0] = va[0] + scale*vb[0]; 60 | vc[1] = va[1] + scale*vb[1]; 61 | vc[2] = va[2] + scale*vb[2]; 62 | } 63 | 64 | void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) 65 | { 66 | cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; 67 | cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; 68 | cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; 69 | } 70 | 71 | vec_t _DotProduct (vec3_t v1, vec3_t v2) 72 | { 73 | return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; 74 | } 75 | 76 | void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out) 77 | { 78 | out[0] = va[0]-vb[0]; 79 | out[1] = va[1]-vb[1]; 80 | out[2] = va[2]-vb[2]; 81 | } 82 | 83 | void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out) 84 | { 85 | out[0] = va[0]+vb[0]; 86 | out[1] = va[1]+vb[1]; 87 | out[2] = va[2]+vb[2]; 88 | } 89 | 90 | void _VectorCopy (vec3_t in, vec3_t out) 91 | { 92 | out[0] = in[0]; 93 | out[1] = in[1]; 94 | out[2] = in[2]; 95 | } 96 | 97 | vec_t VectorNormalize (vec3_t v) 98 | { 99 | int i; 100 | double length; 101 | 102 | length = 0; 103 | for (i=0 ; i< 3 ; i++) 104 | length += v[i]*v[i]; 105 | length = sqrt (length); 106 | if (length == 0) 107 | return 0; 108 | 109 | for (i=0 ; i< 3 ; i++) 110 | v[i] /= length; 111 | 112 | return length; 113 | } 114 | 115 | void VectorInverse (vec3_t v) 116 | { 117 | v[0] = -v[0]; 118 | v[1] = -v[1]; 119 | v[2] = -v[2]; 120 | } 121 | 122 | void VectorScale (vec3_t v, vec_t scale, vec3_t out) 123 | { 124 | out[0] = v[0] * scale; 125 | out[1] = v[1] * scale; 126 | out[2] = v[2] * scale; 127 | } 128 | 129 | -------------------------------------------------------------------------------- /qc/progdefs.h: -------------------------------------------------------------------------------- 1 | 2 | /* file generated by qcc, do not modify */ 3 | 4 | typedef struct 5 | { int pad[28]; 6 | int self; 7 | int other; 8 | int world; 9 | float time; 10 | float frametime; 11 | int newmis; 12 | float force_retouch; 13 | string_t mapname; 14 | float serverflags; 15 | float total_secrets; 16 | float total_monsters; 17 | float found_secrets; 18 | float killed_monsters; 19 | float parm1; 20 | float parm2; 21 | float parm3; 22 | float parm4; 23 | float parm5; 24 | float parm6; 25 | float parm7; 26 | float parm8; 27 | float parm9; 28 | float parm10; 29 | float parm11; 30 | float parm12; 31 | float parm13; 32 | float parm14; 33 | float parm15; 34 | float parm16; 35 | vec3_t v_forward; 36 | vec3_t v_up; 37 | vec3_t v_right; 38 | float trace_allsolid; 39 | float trace_startsolid; 40 | float trace_fraction; 41 | vec3_t trace_endpos; 42 | vec3_t trace_plane_normal; 43 | float trace_plane_dist; 44 | int trace_ent; 45 | float trace_inopen; 46 | float trace_inwater; 47 | int msg_entity; 48 | func_t main; 49 | func_t StartFrame; 50 | func_t PlayerPreThink; 51 | func_t PlayerPostThink; 52 | func_t ClientKill; 53 | func_t ClientConnect; 54 | func_t PutClientInServer; 55 | func_t ClientDisconnect; 56 | func_t SetNewParms; 57 | func_t SetChangeParms; 58 | } globalvars_t; 59 | 60 | typedef struct 61 | { 62 | float modelindex; 63 | vec3_t absmin; 64 | vec3_t absmax; 65 | float ltime; 66 | float lastruntime; 67 | float movetype; 68 | float solid; 69 | vec3_t origin; 70 | vec3_t oldorigin; 71 | vec3_t velocity; 72 | vec3_t angles; 73 | vec3_t avelocity; 74 | string_t classname; 75 | string_t model; 76 | float frame; 77 | float skin; 78 | float effects; 79 | vec3_t mins; 80 | vec3_t maxs; 81 | vec3_t size; 82 | func_t touch; 83 | func_t use; 84 | func_t think; 85 | func_t blocked; 86 | float nextthink; 87 | int groundentity; 88 | float health; 89 | float frags; 90 | float weapon; 91 | string_t weaponmodel; 92 | float weaponframe; 93 | float currentammo; 94 | float ammo_shells; 95 | float ammo_nails; 96 | float ammo_rockets; 97 | float ammo_cells; 98 | float items; 99 | float takedamage; 100 | int chain; 101 | float deadflag; 102 | vec3_t view_ofs; 103 | float button0; 104 | float button1; 105 | float button2; 106 | float impulse; 107 | float fixangle; 108 | vec3_t v_angle; 109 | string_t netname; 110 | int enemy; 111 | float flags; 112 | float colormap; 113 | float team; 114 | float max_health; 115 | float teleport_time; 116 | float armortype; 117 | float armorvalue; 118 | float waterlevel; 119 | float watertype; 120 | float ideal_yaw; 121 | float yaw_speed; 122 | int aiment; 123 | int goalentity; 124 | float spawnflags; 125 | string_t target; 126 | string_t targetname; 127 | float dmg_take; 128 | float dmg_save; 129 | int dmg_inflictor; 130 | int owner; 131 | vec3_t movedir; 132 | string_t message; 133 | float sounds; 134 | string_t noise; 135 | string_t noise1; 136 | string_t noise2; 137 | string_t noise3; 138 | } entvars_t; 139 | 140 | #define PROGHEADER_CRC 54730 141 | -------------------------------------------------------------------------------- /qc/spectate.qc: -------------------------------------------------------------------------------- 1 | /* 2 | spectate.qc 3 | 4 | spectator functions 5 | 6 | PURPOSE 7 | 8 | Copyright (C) 1996-1997 Id Software, Inc. 9 | 10 | This program is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation; either version 2 13 | of the License, or (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 18 | 19 | See the GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to: 23 | 24 | Free Software Foundation, Inc. 25 | 59 Temple Place - Suite 330 26 | Boston, MA 02111-1307, USA 27 | 28 | */ 29 | // Added Aug11'97 by Zoid 30 | // 31 | // These functions are called from the server if they exist. 32 | // Note that Spectators only have one think since they movement code doesn't 33 | // track them much. Impulse commands work as usual, but don't call 34 | // the regular ImpulseCommand handler in weapons.qc since Spectators don't 35 | // have any weapons and things can explode. 36 | // 37 | // --- Zoid. 38 | 39 | /* 40 | =========== 41 | SpectatorConnect 42 | 43 | called when a spectator connects to a server 44 | ============ 45 | */ 46 | void() SpectatorConnect = 47 | { 48 | bprint (PRINT_MEDIUM, "Spectator "); 49 | bprint (PRINT_MEDIUM, self.netname); 50 | bprint (PRINT_MEDIUM, " entered the game\n"); 51 | 52 | self.goalentity = world; // used for impulse 1 below 53 | }; 54 | 55 | /* 56 | =========== 57 | SpectatorDisconnect 58 | 59 | called when a spectator disconnects from a server 60 | ============ 61 | */ 62 | void() SpectatorDisconnect = 63 | { 64 | bprint (PRINT_MEDIUM, "Spectator "); 65 | bprint (PRINT_MEDIUM, self.netname); 66 | bprint (PRINT_MEDIUM, " left the game\n"); 67 | }; 68 | 69 | /* 70 | ================ 71 | SpectatorImpulseCommand 72 | 73 | Called by SpectatorThink if the spectator entered an impulse 74 | ================ 75 | */ 76 | void() SpectatorImpulseCommand = 77 | { 78 | if (self.impulse == 1) { 79 | // teleport the spectator to the next spawn point 80 | // note that if the spectator is tracking, this doesn't do 81 | // much 82 | self.goalentity = find(self.goalentity, classname, "info_player_deathmatch"); 83 | if (self.goalentity == world) 84 | self.goalentity = find(self.goalentity, classname, "info_player_deathmatch"); 85 | if (self.goalentity != world) { 86 | setorigin(self, self.goalentity.origin); 87 | self.angles = self.goalentity.angles; 88 | self.fixangle = TRUE; // turn this way immediately 89 | } 90 | } 91 | 92 | self.impulse = 0; 93 | }; 94 | 95 | /* 96 | ================ 97 | SpectatorThink 98 | 99 | Called every frame after physics are run 100 | ================ 101 | */ 102 | void() SpectatorThink = 103 | { 104 | // self.origin, etc contains spectator position, so you could 105 | // do some neat stuff here 106 | 107 | if (self.impulse) 108 | SpectatorImpulseCommand(); 109 | }; 110 | 111 | 112 | -------------------------------------------------------------------------------- /qbsp.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qbsp", "qbsp\qbsp.vcxproj", "{21D59AF6-0F02-40E5-B4F7-4CF27D6A8C4F}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {743626C6-FD32-4C6D-BA62-F8BEA39F51FD} = {743626C6-FD32-4C6D-BA62-F8BEA39F51FD} 7 | EndProjectSection 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxproj", "{743626C6-FD32-4C6D-BA62-F8BEA39F51FD}" 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vis", "vis\vis.vcxproj", "{DD804337-3C39-41C0-B84A-1FF25CF44ADA}" 12 | EndProject 13 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "light", "light\light.vcxproj", "{769A8669-6F8E-4DDE-B5EA-354FCB02415E}" 14 | ProjectSection(ProjectDependencies) = postProject 15 | {743626C6-FD32-4C6D-BA62-F8BEA39F51FD} = {743626C6-FD32-4C6D-BA62-F8BEA39F51FD} 16 | EndProjectSection 17 | EndProject 18 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qcc", "qcc\qcc.vcxproj", "{F235A057-0EB0-4AA3-AD00-CB1499C88AF2}" 19 | ProjectSection(ProjectDependencies) = postProject 20 | {743626C6-FD32-4C6D-BA62-F8BEA39F51FD} = {743626C6-FD32-4C6D-BA62-F8BEA39F51FD} 21 | EndProjectSection 22 | EndProject 23 | Global 24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 25 | Debug|Win32 = Debug|Win32 26 | Release|Win32 = Release|Win32 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {21D59AF6-0F02-40E5-B4F7-4CF27D6A8C4F}.Debug|Win32.ActiveCfg = Debug|Win32 30 | {21D59AF6-0F02-40E5-B4F7-4CF27D6A8C4F}.Debug|Win32.Build.0 = Debug|Win32 31 | {21D59AF6-0F02-40E5-B4F7-4CF27D6A8C4F}.Release|Win32.ActiveCfg = Release|Win32 32 | {21D59AF6-0F02-40E5-B4F7-4CF27D6A8C4F}.Release|Win32.Build.0 = Release|Win32 33 | {743626C6-FD32-4C6D-BA62-F8BEA39F51FD}.Debug|Win32.ActiveCfg = Debug|Win32 34 | {743626C6-FD32-4C6D-BA62-F8BEA39F51FD}.Debug|Win32.Build.0 = Debug|Win32 35 | {743626C6-FD32-4C6D-BA62-F8BEA39F51FD}.Release|Win32.ActiveCfg = Release|Win32 36 | {743626C6-FD32-4C6D-BA62-F8BEA39F51FD}.Release|Win32.Build.0 = Release|Win32 37 | {DD804337-3C39-41C0-B84A-1FF25CF44ADA}.Debug|Win32.ActiveCfg = Debug|Win32 38 | {DD804337-3C39-41C0-B84A-1FF25CF44ADA}.Debug|Win32.Build.0 = Debug|Win32 39 | {DD804337-3C39-41C0-B84A-1FF25CF44ADA}.Release|Win32.ActiveCfg = Release|Win32 40 | {DD804337-3C39-41C0-B84A-1FF25CF44ADA}.Release|Win32.Build.0 = Release|Win32 41 | {769A8669-6F8E-4DDE-B5EA-354FCB02415E}.Debug|Win32.ActiveCfg = Debug|Win32 42 | {769A8669-6F8E-4DDE-B5EA-354FCB02415E}.Debug|Win32.Build.0 = Debug|Win32 43 | {769A8669-6F8E-4DDE-B5EA-354FCB02415E}.Release|Win32.ActiveCfg = Release|Win32 44 | {769A8669-6F8E-4DDE-B5EA-354FCB02415E}.Release|Win32.Build.0 = Release|Win32 45 | {F235A057-0EB0-4AA3-AD00-CB1499C88AF2}.Debug|Win32.ActiveCfg = Debug|Win32 46 | {F235A057-0EB0-4AA3-AD00-CB1499C88AF2}.Debug|Win32.Build.0 = Debug|Win32 47 | {F235A057-0EB0-4AA3-AD00-CB1499C88AF2}.Release|Win32.ActiveCfg = Release|Win32 48 | {F235A057-0EB0-4AA3-AD00-CB1499C88AF2}.Release|Win32.Build.0 = Release|Win32 49 | EndGlobalSection 50 | GlobalSection(SolutionProperties) = preSolution 51 | HideSolutionNode = FALSE 52 | EndGlobalSection 53 | EndGlobal 54 | -------------------------------------------------------------------------------- /xcode/qcc/qcc.xcodeproj/xcuserdata/fabiensanglard.xcuserdatad/xcschemes/qcc.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /xcode/light/light.xcodeproj/xcuserdata/fabiensanglard.xcuserdatad/xcschemes/light.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /common/cmdlib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // cmdlib.h 21 | 22 | #ifndef __CMDLIB__ 23 | #define __CMDLIB__ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #ifndef __BYTEBOOL__ 34 | #define __BYTEBOOL__ 35 | typedef enum {false, true} qboolean; 36 | typedef unsigned char byte; 37 | #endif 38 | 39 | // the dec offsetof macro doesn't work very well... 40 | #define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier) 41 | 42 | 43 | // set these before calling CheckParm 44 | extern int myargc; 45 | extern char **myargv; 46 | 47 | char *strupr (char *in); 48 | char *strlower (char *in); 49 | int Q_strncasecmp (char *s1, char *s2, int n); 50 | int Q_strcasecmp (char *s1, char *s2); 51 | void Q_getwd (char *out); 52 | 53 | int filelength (FILE *f); 54 | int FileTime (char *path); 55 | 56 | void Q_mkdir (char *path); 57 | 58 | extern char qdir[1024]; 59 | extern char gamedir[1024]; 60 | void SetQdirFromPath (char *path); 61 | char *ExpandPath (char *path); 62 | char *ExpandPathAndArchive (char *path); 63 | 64 | 65 | double I_FloatTime (void); 66 | 67 | void Error (char *error, ...); 68 | int CheckParm (char *check); 69 | 70 | FILE *SafeOpenWrite (char *filename); 71 | FILE *SafeOpenRead (char *filename); 72 | void SafeRead (FILE *f, void *buffer, int count); 73 | void SafeWrite (FILE *f, void *buffer, int count); 74 | 75 | int LoadFile (char *filename, void **bufferptr); 76 | void SaveFile (char *filename, void *buffer, int count); 77 | 78 | void DefaultExtension (char *path, char *extension); 79 | void DefaultPath (char *path, char *basepath); 80 | void StripFilename (char *path); 81 | void StripExtension (char *path); 82 | 83 | void ExtractFilePath (char *path, char *dest); 84 | void ExtractFileBase (char *path, char *dest); 85 | void ExtractFileExtension (char *path, char *dest); 86 | 87 | int ParseNum (char *str); 88 | 89 | short BigShort (short l); 90 | short LittleShort (short l); 91 | int BigLong (int l); 92 | int LittleLong (int l); 93 | float BigFloat (float l); 94 | float LittleFloat (float l); 95 | 96 | 97 | char *COM_Parse (char *data); 98 | 99 | extern char com_token[1024]; 100 | extern qboolean com_eof; 101 | 102 | char *copystring(char *s); 103 | 104 | 105 | void CRC_Init(unsigned short *crcvalue); 106 | void CRC_ProcessByte(unsigned short *crcvalue, byte data); 107 | unsigned short CRC_Value(unsigned short crcvalue); 108 | 109 | void CreatePath (char *path); 110 | void CopyFile (char *from, char *to); 111 | 112 | extern qboolean archive; 113 | extern char archivedir[1024]; 114 | 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /light/light.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // lighting.c 21 | 22 | #include "light.h" 23 | 24 | /* 25 | 26 | NOTES 27 | ----- 28 | 29 | */ 30 | 31 | float scaledist = 1.0; 32 | float scalecos = 0.5; 33 | float rangescale = 0.5; 34 | 35 | byte *filebase, *file_p, *file_end; 36 | 37 | dmodel_t *bspmodel; 38 | int bspfileface; // next surface to dispatch 39 | 40 | vec3_t bsp_origin; 41 | 42 | qboolean extrasamples; 43 | 44 | float minlights[MAX_MAP_FACES]; 45 | 46 | 47 | byte *GetFileSpace (int size) 48 | { 49 | byte *buf; 50 | 51 | LOCK; 52 | file_p = (byte *)(((long)file_p + 3)&~3); 53 | buf = file_p; 54 | file_p += size; 55 | UNLOCK; 56 | if (file_p > file_end) 57 | Error ("GetFileSpace: overrun"); 58 | return buf; 59 | } 60 | 61 | 62 | void LightThread (void *junk) 63 | { 64 | int i; 65 | 66 | while (1) 67 | { 68 | LOCK; 69 | i = bspfileface++; 70 | UNLOCK; 71 | if (i >= numfaces) 72 | return; 73 | 74 | LightFace (i); 75 | } 76 | } 77 | 78 | /* 79 | ============= 80 | LightWorld 81 | ============= 82 | */ 83 | void LightWorld (void) 84 | { 85 | filebase = file_p = dlightdata; 86 | file_end = filebase + MAX_MAP_LIGHTING; 87 | 88 | RunThreadsOn (LightThread); 89 | 90 | lightdatasize = file_p - filebase; 91 | 92 | printf ("lightdatasize: %i\n", lightdatasize); 93 | } 94 | 95 | 96 | /* 97 | ======== 98 | main 99 | 100 | light modelfile 101 | ======== 102 | */ 103 | int main (int argc, char **argv) 104 | { 105 | int i; 106 | double start, end; 107 | char source[1024]; 108 | 109 | printf ("----- LightFaces ----\n"); 110 | 111 | for (i=1 ; i East wall:p[1] 11 | { 12 | ( 432 0 96 ) ( 432 128 96 ) ( 560 0 96 ) bricka2_2 -432 0 0 1 1 //TX1 13 | ( 432 0 -96 ) ( 432 -128 -96 ) ( 560 0 -96 ) bricka2_2 -432 0 0 1 -1 //TX1 14 | ( 432 192 272 ) ( 432 192 400 ) ( 304 192 272 ) bricka2_2 432 272 0 -1 1 //TX1 15 | ( 432 -192 272 ) ( 432 -192 400 ) ( 560 -192 272 ) bricka2_2 -432 272 0 1 1 //TX1 16 | ( 272 0 272 ) ( 272 0 400 ) ( 272 128 272 ) bricka2_2 0 272 0 1 1 //TX1 17 | ( 256 0 272 ) ( 256 0 400 ) ( 256 -128 272 ) bricka2_2 0 272 0 -1 1 //TX1 18 | } 19 | // Brush 1 20 | // Border walls:g[1] -> West wall:p[2] 21 | { 22 | ( 432 0 96 ) ( 432 128 96 ) ( 560 0 96 ) bricka2_2 -432 0 0 1 1 //TX1 23 | ( 432 0 -96 ) ( 432 -128 -96 ) ( 560 0 -96 ) bricka2_2 -432 0 0 1 -1 //TX1 24 | ( 432 192 272 ) ( 432 192 400 ) ( 304 192 272 ) bricka2_2 432 272 0 -1 1 //TX1 25 | ( 432 -192 272 ) ( 432 -192 400 ) ( 560 -192 272 ) bricka2_2 -432 272 0 1 1 //TX1 26 | ( -256 0 272 ) ( -256 0 400 ) ( -256 128 272 ) bricka2_2 0 272 0 1 1 //TX1 27 | ( -272 0 272 ) ( -272 0 400 ) ( -272 -128 272 ) bricka2_2 0 272 0 -1 1 //TX1 28 | } 29 | // Brush 2 30 | // Border walls:g[1] -> North wall:p[3] 31 | { 32 | ( 432 0 96 ) ( 432 128 96 ) ( 560 0 96 ) bricka2_2 -432 0 0 1 1 //TX1 33 | ( 432 0 -96 ) ( 432 -128 -96 ) ( 560 0 -96 ) bricka2_2 -432 0 0 1 -1 //TX1 34 | ( 432 208 272 ) ( 432 208 400 ) ( 304 208 272 ) bricka2_2 432 272 0 -1 1 //TX1 35 | ( 432 192 272 ) ( 432 192 400 ) ( 560 192 272 ) bricka2_2 -432 272 0 1 1 //TX1 36 | ( 256 0 272 ) ( 256 0 400 ) ( 256 128 272 ) bricka2_2 0 272 0 1 1 //TX1 37 | ( -256 0 272 ) ( -256 0 400 ) ( -256 -128 272 ) bricka2_2 0 272 0 -1 1 //TX1 38 | } 39 | // Brush 3 40 | // Border walls:g[1] -> South wall:p[4] 41 | { 42 | ( 432 0 96 ) ( 432 128 96 ) ( 560 0 96 ) bricka2_2 -432 0 0 1 1 //TX1 43 | ( 432 0 -96 ) ( 432 -128 -96 ) ( 560 0 -96 ) bricka2_2 -432 0 0 1 -1 //TX1 44 | ( 432 -192 272 ) ( 432 -192 400 ) ( 304 -192 272 ) bricka2_2 432 272 0 -1 1 //TX1 45 | ( 432 -208 272 ) ( 432 -208 400 ) ( 560 -208 272 ) bricka2_2 -432 272 0 1 1 //TX1 46 | ( 256 0 272 ) ( 256 0 400 ) ( 256 128 272 ) bricka2_2 0 272 0 1 1 //TX1 47 | ( -256 0 272 ) ( -256 0 400 ) ( -256 -128 272 ) bricka2_2 0 272 0 -1 1 //TX1 48 | } 49 | // Brush 4 50 | // Border walls:g[1] -> Sky:p[5] 51 | { 52 | ( 432 0 112 ) ( 432 128 112 ) ( 560 0 112 ) sky1 -432 0 0 1 1 //TX1 53 | ( 432 0 96 ) ( 432 -128 96 ) ( 560 0 96 ) sky1 -432 0 0 1 -1 //TX1 54 | ( 432 192 272 ) ( 432 192 400 ) ( 304 192 272 ) sky1 432 272 0 -1 1 //TX1 55 | ( 432 -192 272 ) ( 432 -192 400 ) ( 560 -192 272 ) sky1 -432 272 0 1 1 //TX1 56 | ( 256 0 272 ) ( 256 0 400 ) ( 256 128 272 ) sky1 0 272 0 1 1 //TX1 57 | ( -256 0 272 ) ( -256 0 400 ) ( -256 -128 272 ) sky1 0 272 0 -1 1 //TX1 58 | } 59 | // Brush 5 60 | // Border walls:g[1] -> Floor:p[6] 61 | { 62 | ( 432 0 -96 ) ( 432 128 -96 ) ( 560 0 -96 ) woodflr1_5 -432 0 0 1 1 //TX1 63 | ( 432 0 -112 ) ( 432 -128 -112 ) ( 560 0 -112 ) woodflr1_5 -432 0 0 1 -1 //TX1 64 | ( 432 192 272 ) ( 432 192 400 ) ( 304 192 272 ) woodflr1_5 432 272 0 -1 1 //TX1 65 | ( 432 -192 272 ) ( 432 -192 400 ) ( 560 -192 272 ) woodflr1_5 -432 272 0 1 1 //TX1 66 | ( 256 0 272 ) ( 256 0 400 ) ( 256 128 272 ) woodflr1_5 0 272 0 1 1 //TX1 67 | ( -256 0 272 ) ( -256 0 400 ) ( -256 -128 272 ) woodflr1_5 0 272 0 -1 1 //TX1 68 | } 69 | } 70 | // Entity 1 71 | // info_player_start:e[2] 72 | { 73 | "classname" "info_player_start" 74 | "origin" "-144 0 -72" 75 | "angle" "360" 76 | } 77 | // Entity 2 78 | // light:e[3] 79 | { 80 | "classname" "light" 81 | "light" "300" 82 | "angle" "360" 83 | "origin" "0 0 0" 84 | } 85 | -------------------------------------------------------------------------------- /vis/vis.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // vis.h 21 | 22 | #include "cmdlib.h" 23 | #include "mathlib.h" 24 | #include "bspfile.h" 25 | 26 | #define MAX_PORTALS 32768 27 | 28 | #define PORTALFILE "PRT1" 29 | 30 | #define ON_EPSILON 0.1 31 | 32 | typedef struct 33 | { 34 | vec3_t normal; 35 | float dist; 36 | } plane_t; 37 | 38 | typedef struct 39 | { 40 | qboolean original; // don't free, it's part of the portal 41 | int numpoints; 42 | vec3_t points[8]; // variable sized 43 | } winding_t; 44 | 45 | #define MAX_POINTS_ON_WINDING 64 46 | 47 | winding_t *NewWinding (int points); 48 | void FreeWinding (winding_t *w); 49 | winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon); 50 | winding_t *CopyWinding (winding_t *w); 51 | 52 | 53 | typedef enum {stat_none, stat_working, stat_done} vstatus_t; 54 | typedef struct 55 | { 56 | plane_t plane; // normal pointing into neighbor 57 | int leaf; // neighbor //FCS: WTF is this and where is it set ? 58 | winding_t *winding; 59 | vstatus_t status; 60 | byte *visbits; 61 | byte *mightsee; 62 | int nummightsee; 63 | int numcansee; 64 | } portal_t; 65 | 66 | typedef struct seperating_plane_s 67 | { 68 | struct seperating_plane_s *next; 69 | plane_t plane; // from portal is on positive side 70 | } sep_t; 71 | 72 | 73 | typedef struct passage_s 74 | { 75 | struct passage_s *next; 76 | int from, to; // leaf numbers 77 | sep_t *planes; 78 | } passage_t; 79 | 80 | #define MAX_PORTALS_ON_LEAF 128 81 | typedef struct leaf_s 82 | { 83 | int numportals; 84 | passage_t *passages; 85 | portal_t *portals[MAX_PORTALS_ON_LEAF]; 86 | } leaf_t; 87 | 88 | 89 | typedef struct pstack_s 90 | { 91 | struct pstack_s *next; 92 | leaf_t *leaf; 93 | portal_t *portal; // portal exiting 94 | winding_t *source, *pass; 95 | plane_t portalplane; 96 | byte *mightsee; // bit string 97 | } pstack_t; 98 | 99 | typedef struct 100 | { 101 | byte *leafvis; // bit string 102 | portal_t *base; 103 | pstack_t pstack_head; 104 | } threaddata_t; 105 | 106 | //FCS __unix__ also include macosx 107 | #if defined(__alpha) || defined(__APPLE__) 108 | #include 109 | extern pthread_mutex_t *my_mutex; 110 | #define LOCK pthread_mutex_lock (my_mutex) 111 | #define UNLOCK pthread_mutex_unlock (my_mutex) 112 | #else 113 | #define LOCK 114 | #define UNLOCK 115 | #endif 116 | 117 | 118 | extern int numportals; 119 | extern int portalleafs; 120 | 121 | extern portal_t *portals; 122 | extern leaf_t *leafs; 123 | 124 | extern int c_portaltest, c_portalpass, c_portalcheck; 125 | extern int c_portalskip, c_leafskip; 126 | extern int c_vistest, c_mighttest; 127 | extern int c_chains; 128 | 129 | extern byte *vismap, *vismap_p, *vismap_end; // past visfile 130 | 131 | extern qboolean showgetleaf; 132 | extern int testlevel; 133 | 134 | extern byte *uncompressed; 135 | extern int bitbytes; 136 | extern int bitlongs; 137 | 138 | 139 | void LeafFlow (int leafnum); 140 | void BasePortalVis (void); 141 | 142 | void PortalFlow (portal_t *p); 143 | 144 | void CalcAmbientSounds (void); 145 | -------------------------------------------------------------------------------- /qcc/pr_comp.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | // this file is shared by quake and qcc 22 | 23 | typedef int func_t; 24 | typedef int string_t; 25 | 26 | typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer} etype_t; 27 | 28 | 29 | #define OFS_NULL 0 30 | #define OFS_RETURN 1 31 | #define OFS_PARM0 4 // leave 3 ofs for each parm to hold vectors 32 | #define OFS_PARM1 7 33 | #define OFS_PARM2 10 34 | #define OFS_PARM3 13 35 | #define OFS_PARM4 16 36 | #define OFS_PARM5 19 37 | #define OFS_PARM6 22 38 | #define OFS_PARM7 25 39 | #define RESERVED_OFS 28 40 | 41 | 42 | enum { 43 | OP_DONE, 44 | OP_MUL_F, 45 | OP_MUL_V, 46 | OP_MUL_FV, 47 | OP_MUL_VF, 48 | OP_DIV_F, 49 | OP_ADD_F, 50 | OP_ADD_V, 51 | OP_SUB_F, 52 | OP_SUB_V, 53 | 54 | OP_EQ_F, 55 | OP_EQ_V, 56 | OP_EQ_S, 57 | OP_EQ_E, 58 | OP_EQ_FNC, 59 | 60 | OP_NE_F, 61 | OP_NE_V, 62 | OP_NE_S, 63 | OP_NE_E, 64 | OP_NE_FNC, 65 | 66 | OP_LE, 67 | OP_GE, 68 | OP_LT, 69 | OP_GT, 70 | 71 | OP_LOAD_F, 72 | OP_LOAD_V, 73 | OP_LOAD_S, 74 | OP_LOAD_ENT, 75 | OP_LOAD_FLD, 76 | OP_LOAD_FNC, 77 | 78 | OP_ADDRESS, 79 | 80 | OP_STORE_F, 81 | OP_STORE_V, 82 | OP_STORE_S, 83 | OP_STORE_ENT, 84 | OP_STORE_FLD, 85 | OP_STORE_FNC, 86 | 87 | OP_STOREP_F, 88 | OP_STOREP_V, 89 | OP_STOREP_S, 90 | OP_STOREP_ENT, 91 | OP_STOREP_FLD, 92 | OP_STOREP_FNC, 93 | 94 | OP_RETURN, 95 | OP_NOT_F, 96 | OP_NOT_V, 97 | OP_NOT_S, 98 | OP_NOT_ENT, 99 | OP_NOT_FNC, 100 | OP_IF, 101 | OP_IFNOT, 102 | OP_CALL0, 103 | OP_CALL1, 104 | OP_CALL2, 105 | OP_CALL3, 106 | OP_CALL4, 107 | OP_CALL5, 108 | OP_CALL6, 109 | OP_CALL7, 110 | OP_CALL8, 111 | OP_STATE, 112 | OP_GOTO, 113 | OP_AND, 114 | OP_OR, 115 | 116 | OP_BITAND, 117 | OP_BITOR 118 | }; 119 | 120 | 121 | typedef struct statement_s 122 | { 123 | unsigned short op; 124 | short a,b,c; 125 | } dstatement_t; 126 | 127 | typedef struct 128 | { 129 | unsigned short type; // if DEF_SAVEGLOBGAL bit is set 130 | // the variable needs to be saved in savegames 131 | unsigned short ofs; 132 | int s_name; 133 | } ddef_t; 134 | #define DEF_SAVEGLOBGAL (1<<15) 135 | 136 | #define MAX_PARMS 8 137 | 138 | typedef struct 139 | { 140 | int first_statement; // negative numbers are builtins 141 | int parm_start; 142 | int locals; // total ints of parms + locals 143 | 144 | int profile; // runtime 145 | 146 | int s_name; 147 | int s_file; // source file defined in 148 | 149 | int numparms; 150 | byte parm_size[MAX_PARMS]; 151 | } dfunction_t; 152 | 153 | 154 | #define PROG_VERSION 6 155 | typedef struct 156 | { 157 | int version; 158 | int crc; // check of header file 159 | 160 | int ofs_statements; 161 | int numstatements; // statement 0 is an error 162 | 163 | int ofs_globaldefs; 164 | int numglobaldefs; 165 | 166 | int ofs_fielddefs; 167 | int numfielddefs; 168 | 169 | int ofs_functions; 170 | int numfunctions; // function 0 is an empty 171 | 172 | int ofs_strings; 173 | int numstrings; // first string is a null string 174 | 175 | int ofs_globals; 176 | int numglobals; 177 | 178 | int entityfields; 179 | } dprograms_t; 180 | 181 | -------------------------------------------------------------------------------- /vis/soundpvs.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | #include "vis.h" 22 | 23 | /* 24 | 25 | Some textures (sky, water, slime, lava) are considered ambien sound emiters. 26 | Find an aproximate distance to the nearest emiter of each class for each leaf. 27 | 28 | */ 29 | 30 | 31 | /* 32 | ==================== 33 | SurfaceBBox 34 | 35 | ==================== 36 | */ 37 | void SurfaceBBox (dface_t *s, vec3_t mins, vec3_t maxs) 38 | { 39 | int i, j; 40 | int e; 41 | int vi; 42 | float *v; 43 | 44 | mins[0] = mins[1] = 999999; 45 | maxs[0] = maxs[1] = -99999; 46 | 47 | for (i=0 ; inumedges ; i++) 48 | { 49 | e = dsurfedges[s->firstedge+i]; 50 | if (e >= 0) 51 | vi = dedges[e].v[0]; 52 | else 53 | vi = dedges[-e].v[1]; 54 | v = dvertexes[vi].point; 55 | 56 | for (j=0 ; j<3 ; j++) 57 | { 58 | if (v[j] < mins[j]) 59 | mins[j] = v[j]; 60 | if (v[j] > maxs[j]) 61 | maxs[j] = v[j]; 62 | } 63 | } 64 | } 65 | 66 | 67 | /* 68 | ==================== 69 | CalcAmbientSounds 70 | 71 | ==================== 72 | */ 73 | void CalcAmbientSounds (void) 74 | { 75 | int i, j, k, l; 76 | dleaf_t *leaf, *hit; 77 | byte *vis; 78 | dface_t *surf; 79 | vec3_t mins, maxs; 80 | float d, maxd; 81 | int ambient_type; 82 | texinfo_t *info; 83 | miptex_t *miptex; 84 | int ofs; 85 | float dists[NUM_AMBIENTS]; 86 | float vol; 87 | 88 | for (i=0 ; i< portalleafs ; i++) 89 | { 90 | leaf = &dleafs[i+1]; 91 | 92 | // 93 | // clear ambients 94 | // 95 | for (j=0 ; j>3] & (1<<(j&7))) ) 103 | continue; 104 | 105 | // 106 | // check this leaf for sound textures 107 | // 108 | hit = &dleafs[j+1]; 109 | 110 | for (k=0 ; k< hit->nummarksurfaces ; k++) 111 | { 112 | surf = &dfaces[dmarksurfaces[hit->firstmarksurface + k]]; 113 | info = &texinfo[surf->texinfo]; 114 | ofs = ((dmiptexlump_t *)dtexdata)->dataofs[info->miptex]; 115 | miptex = (miptex_t *)(&dtexdata[ofs]); 116 | 117 | if ( !Q_strncasecmp (miptex->name, "*water", 6) ) 118 | ambient_type = AMBIENT_WATER; 119 | else if ( !Q_strncasecmp (miptex->name, "sky", 3) ) 120 | ambient_type = AMBIENT_SKY; 121 | else if ( !Q_strncasecmp (miptex->name, "*slime", 6) ) 122 | ambient_type = AMBIENT_WATER; // AMBIENT_SLIME; 123 | else if ( !Q_strncasecmp (miptex->name, "*lava", 6) ) 124 | ambient_type = AMBIENT_LAVA; 125 | else if ( !Q_strncasecmp (miptex->name, "*04water", 8) ) 126 | ambient_type = AMBIENT_WATER; 127 | else 128 | continue; 129 | 130 | // find distance from source leaf to polygon 131 | SurfaceBBox (surf, mins, maxs); 132 | maxd = 0; 133 | for (l=0 ; l<3 ; l++) 134 | { 135 | if (mins[l] > leaf->maxs[l]) 136 | d = mins[l] - leaf->maxs[l]; 137 | else if (maxs[l] < leaf->mins[l]) 138 | d = leaf->mins[l] - mins[l]; 139 | else 140 | d = 0; 141 | if (d > maxd) 142 | maxd = d; 143 | } 144 | 145 | maxd = 0.25; 146 | if (maxd < dists[ambient_type]) 147 | dists[ambient_type] = maxd; 148 | } 149 | } 150 | 151 | for (j=0 ; jambient_level[j] = vol*255; 162 | } 163 | } 164 | } 165 | 166 | -------------------------------------------------------------------------------- /qc/buttons.qc: -------------------------------------------------------------------------------- 1 | /* 2 | buttons.qc 3 | 4 | button and multiple button 5 | 6 | Copyright (C) 1996-1997 Id Software, Inc. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 | 17 | See the GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to: 21 | 22 | Free Software Foundation, Inc. 23 | 59 Temple Place - Suite 330 24 | Boston, MA 02111-1307, USA 25 | 26 | */ 27 | 28 | void() button_wait; 29 | void() button_return; 30 | 31 | void() button_wait = 32 | { 33 | self.state = STATE_TOP; 34 | self.nextthink = self.ltime + self.wait; 35 | self.think = button_return; 36 | activator = self.enemy; 37 | SUB_UseTargets(); 38 | self.frame = 1; // use alternate textures 39 | }; 40 | 41 | void() button_done = 42 | { 43 | self.state = STATE_BOTTOM; 44 | }; 45 | 46 | void() button_return = 47 | { 48 | self.state = STATE_DOWN; 49 | SUB_CalcMove (self.pos1, self.speed, button_done); 50 | self.frame = 0; // use normal textures 51 | if (self.health) 52 | self.takedamage = DAMAGE_YES; // can be shot again 53 | }; 54 | 55 | 56 | void() button_blocked = 57 | { // do nothing, just don't ome all the way back out 58 | }; 59 | 60 | 61 | void() button_fire = 62 | { 63 | if (self.state == STATE_UP || self.state == STATE_TOP) 64 | return; 65 | 66 | sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM); 67 | 68 | self.state = STATE_UP; 69 | SUB_CalcMove (self.pos2, self.speed, button_wait); 70 | }; 71 | 72 | 73 | void() button_use = 74 | { 75 | self.enemy = activator; 76 | button_fire (); 77 | }; 78 | 79 | void() button_touch = 80 | { 81 | if (other.classname != "player") 82 | return; 83 | self.enemy = other; 84 | button_fire (); 85 | }; 86 | 87 | void() button_killed = 88 | { 89 | self.enemy = damage_attacker; 90 | self.health = self.max_health; 91 | self.takedamage = DAMAGE_NO; // wil be reset upon return 92 | button_fire (); 93 | }; 94 | 95 | 96 | /*QUAKED func_button (0 .5 .8) ? 97 | When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again. 98 | 99 | "angle" determines the opening direction 100 | "target" all entities with a matching targetname will be used 101 | "speed" override the default 40 speed 102 | "wait" override the default 1 second wait (-1 = never return) 103 | "lip" override the default 4 pixel lip remaining at end of move 104 | "health" if set, the button must be killed instead of touched 105 | "sounds" 106 | 0) steam metal 107 | 1) wooden clunk 108 | 2) metallic click 109 | 3) in-out 110 | */ 111 | void() func_button = 112 | { 113 | local float gtemp, ftemp; 114 | 115 | if (self.sounds == 0) 116 | { 117 | precache_sound ("buttons/airbut1.wav"); 118 | self.noise = "buttons/airbut1.wav"; 119 | } 120 | if (self.sounds == 1) 121 | { 122 | precache_sound ("buttons/switch21.wav"); 123 | self.noise = "buttons/switch21.wav"; 124 | } 125 | if (self.sounds == 2) 126 | { 127 | precache_sound ("buttons/switch02.wav"); 128 | self.noise = "buttons/switch02.wav"; 129 | } 130 | if (self.sounds == 3) 131 | { 132 | precache_sound ("buttons/switch04.wav"); 133 | self.noise = "buttons/switch04.wav"; 134 | } 135 | 136 | SetMovedir (); 137 | 138 | self.movetype = MOVETYPE_PUSH; 139 | self.solid = SOLID_BSP; 140 | setmodel (self, self.model); 141 | 142 | self.blocked = button_blocked; 143 | self.use = button_use; 144 | 145 | if (self.health) 146 | { 147 | self.max_health = self.health; 148 | self.th_die = button_killed; 149 | self.takedamage = DAMAGE_YES; 150 | } 151 | else 152 | self.touch = button_touch; 153 | 154 | if (!self.speed) 155 | self.speed = 40; 156 | if (!self.wait) 157 | self.wait = 1; 158 | if (!self.lip) 159 | self.lip = 4; 160 | 161 | self.state = STATE_BOTTOM; 162 | 163 | self.pos1 = self.origin; 164 | self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip); 165 | }; 166 | 167 | -------------------------------------------------------------------------------- /common/scriplib.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // scriplib.c 21 | 22 | #include "cmdlib.h" 23 | #include "scriplib.h" 24 | 25 | /* 26 | ============================================================================= 27 | 28 | PARSING STUFF 29 | 30 | ============================================================================= 31 | */ 32 | 33 | char token[MAXTOKEN]; 34 | char *scriptbuffer,*script_p,*scriptend_p; 35 | int grabbed; 36 | int scriptline; 37 | qboolean endofscript; 38 | qboolean tokenready; // only true if UnGetToken was just called 39 | 40 | /* 41 | ============== 42 | = 43 | = LoadScriptFile 44 | = 45 | ============== 46 | */ 47 | 48 | void LoadScriptFile (char *filename) 49 | { 50 | int size; 51 | 52 | size = LoadFile (filename, (void **)&scriptbuffer); 53 | 54 | script_p = scriptbuffer; 55 | scriptend_p = script_p + size; 56 | scriptline = 1; 57 | endofscript = false; 58 | tokenready = false; 59 | } 60 | 61 | 62 | /* 63 | ============== 64 | = 65 | = UnGetToken 66 | = 67 | = Signals that the current token was not used, and should be reported 68 | = for the next GetToken. Note that 69 | 70 | GetToken (true); 71 | UnGetToken (); 72 | GetToken (false); 73 | 74 | = could cross a line boundary. 75 | = 76 | ============== 77 | */ 78 | 79 | void UnGetToken (void) 80 | { 81 | tokenready = true; 82 | } 83 | 84 | 85 | /* 86 | ============== 87 | GetToken 88 | ============== 89 | */ 90 | qboolean GetToken (qboolean crossline) 91 | { 92 | char *token_p; 93 | 94 | if (tokenready) // is a token allready waiting? 95 | { 96 | tokenready = false; 97 | return true; 98 | } 99 | 100 | if (script_p >= scriptend_p) 101 | { 102 | if (!crossline) 103 | Error ("Line %i is incomplete\n",scriptline); 104 | endofscript = true; 105 | return false; 106 | } 107 | 108 | // 109 | // skip space 110 | // 111 | skipspace: 112 | while (*script_p <= 32) 113 | { 114 | if (script_p >= scriptend_p) 115 | { 116 | if (!crossline) 117 | Error ("Line %i is incomplete\n",scriptline); 118 | endofscript = true; 119 | return true; 120 | } 121 | if (*script_p++ == '\n') 122 | { 123 | if (!crossline) 124 | Error ("Line %i is incomplete\n",scriptline); 125 | scriptline++; 126 | } 127 | } 128 | 129 | if (script_p >= scriptend_p) 130 | { 131 | if (!crossline) 132 | Error ("Line %i is incomplete\n",scriptline); 133 | endofscript = true; 134 | return true; 135 | } 136 | 137 | if (*script_p == ';' || *script_p == '#') // semicolon is comment field 138 | { // also make # a comment field 139 | if (!crossline) 140 | Error ("Line %i is incomplete\n",scriptline); 141 | while (*script_p++ != '\n') 142 | if (script_p >= scriptend_p) 143 | { 144 | endofscript = true; 145 | return false; 146 | } 147 | goto skipspace; 148 | } 149 | 150 | // 151 | // copy token 152 | // 153 | token_p = token; 154 | 155 | while ( *script_p > 32 && *script_p != ';') 156 | { 157 | *token_p++ = *script_p++; 158 | if (script_p == scriptend_p) 159 | break; 160 | if (token_p == &token[MAXTOKEN]) 161 | Error ("Token too large on line %i\n",scriptline); 162 | } 163 | 164 | *token_p = 0; 165 | return true; 166 | } 167 | 168 | 169 | /* 170 | ============== 171 | = 172 | = TokenAvailable 173 | = 174 | = Returns true if there is another token on the line 175 | = 176 | ============== 177 | */ 178 | 179 | qboolean TokenAvailable (void) 180 | { 181 | char *search_p; 182 | 183 | search_p = script_p; 184 | 185 | if (search_p >= scriptend_p) 186 | return false; 187 | 188 | while ( *search_p <= 32) 189 | { 190 | if (*search_p == '\n') 191 | return false; 192 | search_p++; 193 | if (search_p == scriptend_p) 194 | return false; 195 | 196 | } 197 | 198 | if (*search_p == ';') 199 | return false; 200 | 201 | return true; 202 | } 203 | 204 | 205 | -------------------------------------------------------------------------------- /common/common.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 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 | {743626C6-FD32-4C6D-BA62-F8BEA39F51FD} 38 | Win32Proj 39 | common 40 | 41 | 42 | 43 | StaticLibrary 44 | true 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | true 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | true 65 | 66 | 67 | false 68 | 69 | 70 | 71 | 72 | 73 | Level3 74 | Disabled 75 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 76 | 77 | 78 | Console 79 | true 80 | 81 | 82 | 83 | 84 | Level3 85 | 86 | 87 | MaxSpeed 88 | true 89 | true 90 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | 92 | 93 | Console 94 | true 95 | true 96 | true 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /vis/vis.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {743626c6-fd32-4c6d-ba62-f8bea39f51fd} 34 | 35 | 36 | 37 | {DD804337-3C39-41C0-B84A-1FF25CF44ADA} 38 | Win32Proj 39 | vis 40 | 41 | 42 | 43 | Application 44 | true 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | true 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | true 65 | 66 | 67 | false 68 | 69 | 70 | 71 | 72 | 73 | Level3 74 | Disabled 75 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 76 | ../common 77 | 78 | 79 | Console 80 | true 81 | 82 | 83 | 84 | 85 | Level3 86 | 87 | 88 | MaxSpeed 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | 93 | 94 | Console 95 | true 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /qcc/qcc.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {F235A057-0EB0-4AA3-AD00-CB1499C88AF2} 15 | Win32Proj 16 | qcc 17 | 18 | 19 | 20 | Application 21 | true 22 | Unicode 23 | 24 | 25 | Application 26 | false 27 | true 28 | Unicode 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | Level3 51 | Disabled 52 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 53 | ../common 54 | 55 | 56 | Console 57 | true 58 | 59 | 60 | 61 | 62 | Level3 63 | 64 | 65 | MaxSpeed 66 | true 67 | true 68 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 69 | 70 | 71 | Console 72 | true 73 | true 74 | true 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | {743626c6-fd32-4c6d-ba62-f8bea39f51fd} 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /light/light.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {769A8669-6F8E-4DDE-B5EA-354FCB02415E} 15 | Win32Proj 16 | light 17 | 18 | 19 | 20 | Application 21 | true 22 | Unicode 23 | 24 | 25 | Application 26 | false 27 | true 28 | Unicode 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | Level3 51 | Disabled 52 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 53 | ..\common 54 | 55 | 56 | Console 57 | true 58 | 59 | 60 | 61 | 62 | Level3 63 | 64 | 65 | MaxSpeed 66 | true 67 | true 68 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 69 | 70 | 71 | Console 72 | true 73 | true 74 | true 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 | {743626c6-fd32-4c6d-ba62-f8bea39f51fd} 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /light/trace.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // trace.c 21 | 22 | #include "light.h" 23 | 24 | typedef struct tnode_s 25 | { 26 | int type; 27 | vec3_t normal; 28 | float dist; 29 | int children[2]; 30 | int pad; 31 | } tnode_t; 32 | 33 | tnode_t *tnodes, *tnode_p; 34 | 35 | /* 36 | ============== 37 | MakeTnode 38 | 39 | Converts the disk node structure into the efficient tracing structure 40 | ============== 41 | */ 42 | void MakeTnode (int nodenum) 43 | { 44 | tnode_t *t; 45 | dplane_t *plane; 46 | int i; 47 | dnode_t *node; 48 | 49 | t = tnode_p++; 50 | 51 | node = dnodes + nodenum; 52 | plane = dplanes + node->planenum; 53 | 54 | t->type = plane->type; 55 | VectorCopy (plane->normal, t->normal); 56 | t->dist = plane->dist; 57 | 58 | for (i=0 ; i<2 ; i++) 59 | { 60 | if (node->children[i] < 0) 61 | t->children[i] = dleafs[-node->children[i] - 1].contents; 62 | else 63 | { 64 | t->children[i] = tnode_p - tnodes; 65 | MakeTnode (node->children[i]); 66 | } 67 | } 68 | 69 | } 70 | 71 | 72 | /* 73 | ============= 74 | MakeTnodes 75 | 76 | Loads the node structure out of a .bsp file to be used for light occlusion 77 | ============= 78 | */ 79 | void MakeTnodes (dmodel_t *bm) 80 | { 81 | tnode_p = tnodes = malloc(numnodes * sizeof(tnode_t)); 82 | 83 | MakeTnode (0); 84 | } 85 | 86 | 87 | 88 | /* 89 | ============================================================================== 90 | 91 | LINE TRACING 92 | 93 | The major lighting operation is a point to point visibility test, performed 94 | by recursive subdivision of the line by the BSP tree. 95 | 96 | ============================================================================== 97 | */ 98 | 99 | typedef struct 100 | { 101 | vec3_t backpt; 102 | int side; 103 | int node; 104 | } tracestack_t; 105 | 106 | 107 | /* 108 | ============== 109 | TestLine 110 | ============== 111 | */ 112 | qboolean TestLine (vec3_t start, vec3_t stop) 113 | { 114 | int node; 115 | float front, back; 116 | tracestack_t *tstack_p; 117 | int side; 118 | float frontx,fronty, frontz, backx, backy, backz; 119 | tracestack_t tracestack[64]; 120 | tnode_t *tnode; 121 | 122 | frontx = start[0]; 123 | fronty = start[1]; 124 | frontz = start[2]; 125 | backx = stop[0]; 126 | backy = stop[1]; 127 | backz = stop[2]; 128 | 129 | tstack_p = tracestack; 130 | node = 0; 131 | 132 | while (1) 133 | { 134 | while (node < 0 && node != CONTENTS_SOLID) 135 | { 136 | // pop up the stack for a back side 137 | tstack_p--; 138 | if (tstack_p < tracestack) 139 | return true; 140 | node = tstack_p->node; 141 | 142 | // set the hit point for this plane 143 | 144 | frontx = backx; 145 | fronty = backy; 146 | frontz = backz; 147 | 148 | // go down the back side 149 | 150 | backx = tstack_p->backpt[0]; 151 | backy = tstack_p->backpt[1]; 152 | backz = tstack_p->backpt[2]; 153 | 154 | node = tnodes[tstack_p->node].children[!tstack_p->side]; 155 | } 156 | 157 | if (node == CONTENTS_SOLID) 158 | return false; // DONE! 159 | 160 | tnode = &tnodes[node]; 161 | 162 | switch (tnode->type) 163 | { 164 | case PLANE_X: 165 | front = frontx - tnode->dist; 166 | back = backx - tnode->dist; 167 | break; 168 | case PLANE_Y: 169 | front = fronty - tnode->dist; 170 | back = backy - tnode->dist; 171 | break; 172 | case PLANE_Z: 173 | front = frontz - tnode->dist; 174 | back = backz - tnode->dist; 175 | break; 176 | default: 177 | front = (frontx*tnode->normal[0] + fronty*tnode->normal[1] + frontz*tnode->normal[2]) - tnode->dist; 178 | back = (backx*tnode->normal[0] + backy*tnode->normal[1] + backz*tnode->normal[2]) - tnode->dist; 179 | break; 180 | } 181 | 182 | if (front > -ON_EPSILON && back > -ON_EPSILON) 183 | // if (front > 0 && back > 0) 184 | { 185 | node = tnode->children[0]; 186 | continue; 187 | } 188 | 189 | if (front < ON_EPSILON && back < ON_EPSILON) 190 | // if (front <= 0 && back <= 0) 191 | { 192 | node = tnode->children[1]; 193 | continue; 194 | } 195 | 196 | side = front < 0; 197 | 198 | front = front / (front-back); 199 | 200 | tstack_p->node = node; 201 | tstack_p->side = side; 202 | tstack_p->backpt[0] = backx; 203 | tstack_p->backpt[1] = backy; 204 | tstack_p->backpt[2] = backz; 205 | 206 | tstack_p++; 207 | 208 | backx = frontx + front*(backx-frontx); 209 | backy = fronty + front*(backy-fronty); 210 | backz = frontz + front*(backz-frontz); 211 | 212 | node = tnode->children[side]; 213 | } 214 | } 215 | 216 | 217 | -------------------------------------------------------------------------------- /common/trilib.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // 21 | // trilib.c: library for loading triangles from an Alias triangle file 22 | // 23 | 24 | #include 25 | #include "cmdlib.h" 26 | #include "mathlib.h" 27 | #include "trilib.h" 28 | 29 | // on disk representation of a face 30 | 31 | 32 | #define FLOAT_START 99999.0 33 | #define FLOAT_END -FLOAT_START 34 | #define MAGIC 123322 35 | 36 | //#define NOISY 1 37 | 38 | typedef struct { 39 | float v[3]; 40 | } vector; 41 | 42 | typedef struct 43 | { 44 | vector n; /* normal */ 45 | vector p; /* point */ 46 | vector c; /* color */ 47 | float u; /* u */ 48 | float v; /* v */ 49 | } aliaspoint_t; 50 | 51 | typedef struct { 52 | aliaspoint_t pt[3]; 53 | } tf_triangle; 54 | 55 | 56 | void ByteSwapTri (tf_triangle *tri) 57 | { 58 | int i; 59 | 60 | for (i=0 ; iverts[j][k] = tri.pt[j].p.v[k]; 175 | } 176 | } 177 | 178 | ptri++; 179 | 180 | if ((ptri - *pptri) >= MAXTRIANGLES) 181 | Error ("Error: too many triangles; increase MAXTRIANGLES\n"); 182 | } 183 | } 184 | 185 | *numtriangles = ptri - *pptri; 186 | 187 | fclose (input); 188 | } 189 | 190 | -------------------------------------------------------------------------------- /qbsp/qbsp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {21D59AF6-0F02-40E5-B4F7-4CF27D6A8C4F} 15 | Win32Proj 16 | qbsp 17 | 18 | 19 | 20 | Application 21 | true 22 | Unicode 23 | 24 | 25 | Application 26 | false 27 | true 28 | Unicode 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | Level3 51 | Disabled 52 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 53 | ..\common;%(AdditionalIncludeDirectories) 54 | 55 | 56 | Console 57 | true 58 | %(AdditionalDependencies) 59 | 60 | 61 | 62 | 63 | Level3 64 | 65 | 66 | MaxSpeed 67 | true 68 | true 69 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 70 | 71 | 72 | Console 73 | true 74 | true 75 | true 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | {743626c6-fd32-4c6d-ba62-f8bea39f51fd} 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /common/threads.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | #include "cmdlib.h" 22 | #include "threads.h" 23 | 24 | #define MAX_THREADS 64 25 | 26 | int dispatch; 27 | int workcount; 28 | int oldf; 29 | qboolean pacifier; 30 | 31 | /* 32 | ============= 33 | GetThreadWork 34 | 35 | ============= 36 | */ 37 | int GetThreadWork (void) 38 | { 39 | int r; 40 | int f; 41 | 42 | ThreadLock (); 43 | 44 | if (dispatch == workcount) 45 | { 46 | ThreadUnlock (); 47 | return -1; 48 | } 49 | 50 | f = 10*dispatch / workcount; 51 | if (f != oldf) 52 | { 53 | oldf = f; 54 | if (pacifier) 55 | printf ("%i...", f); 56 | } 57 | 58 | r = dispatch; 59 | dispatch++; 60 | ThreadUnlock (); 61 | 62 | return r; 63 | } 64 | 65 | 66 | 67 | /* 68 | =================================================================== 69 | 70 | WIN32 71 | 72 | =================================================================== 73 | */ 74 | #ifdef WIN32 75 | 76 | #define USED 77 | 78 | #include 79 | 80 | int numthreads = 1; 81 | CRITICAL_SECTION crit; 82 | 83 | void ThreadLock (void) 84 | { 85 | EnterCriticalSection (&crit); 86 | } 87 | 88 | void ThreadUnlock (void) 89 | { 90 | LeaveCriticalSection (&crit); 91 | } 92 | 93 | /* 94 | ============= 95 | RunThreadsOn 96 | ============= 97 | */ 98 | void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) 99 | { 100 | int threadid[MAX_THREADS]; 101 | HANDLE threadhandle[MAX_THREADS]; 102 | int i; 103 | 104 | dispatch = 0; 105 | workcount = workcnt; 106 | oldf = -1; 107 | pacifier = showpacifier; 108 | 109 | // 110 | // run threads in parallel 111 | // 112 | InitializeCriticalSection (&crit); 113 | for (i=0 ; i 148 | 149 | pthread_mutex_t *my_mutex; 150 | 151 | void ThreadLock (void) 152 | { 153 | if (my_mutex) 154 | pthread_mutex_lock (my_mutex); 155 | } 156 | 157 | void ThreadUnlock (void) 158 | { 159 | if (my_mutex) 160 | pthread_mutex_unlock (my_mutex); 161 | } 162 | 163 | 164 | /* 165 | ============= 166 | RunThreadsOn 167 | ============= 168 | */ 169 | void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) 170 | { 171 | int i; 172 | pthread_t work_threads[MAX_THREADS]; 173 | pthread_addr_t status; 174 | pthread_attr_t attrib; 175 | pthread_mutexattr_t mattrib; 176 | 177 | dispatch = 0; 178 | workcount = workcnt; 179 | oldf = -1; 180 | pacifier = showpacifier; 181 | 182 | if (!my_mutex) 183 | { 184 | my_mutex = malloc (sizeof(*my_mutex)); 185 | if (pthread_mutexattr_create (&mattrib) == -1) 186 | Error ("pthread_mutex_attr_create failed"); 187 | if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) 188 | Error ("pthread_mutexattr_setkind_np failed"); 189 | if (pthread_mutex_init (my_mutex, mattrib) == -1) 190 | Error ("pthread_mutex_init failed"); 191 | } 192 | 193 | if (pthread_attr_create (&attrib) == -1) 194 | Error ("pthread_attr_create failed"); 195 | if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) 196 | Error ("pthread_attr_setstacksize failed"); 197 | 198 | for (i=0 ; icontents) 35 | return node; 36 | 37 | d = DotProduct (planes[node->planenum].normal, point) - planes[node->planenum]. dist; 38 | 39 | if (d > 0) 40 | return PointInLeaf (node->children[0], point); 41 | 42 | return PointInLeaf (node->children[1], point); 43 | } 44 | 45 | /* 46 | =========== 47 | PlaceOccupant 48 | =========== 49 | */ 50 | qboolean PlaceOccupant (int num, vec3_t point, node_t *headnode) 51 | { 52 | node_t *n; 53 | 54 | n = PointInLeaf (headnode, point); 55 | if (n->contents == CONTENTS_SOLID) 56 | return false; 57 | n->occupied = num; 58 | return true; 59 | } 60 | 61 | 62 | /* 63 | ============== 64 | MarkLeakTrail 65 | ============== 66 | */ 67 | portal_t *prevleaknode; 68 | FILE *leakfile; 69 | void MarkLeakTrail (portal_t *n2) 70 | { 71 | int i, j; 72 | vec3_t p1, p2, dir; 73 | float len; 74 | portal_t *n1; 75 | 76 | if (hullnum) 77 | return; 78 | 79 | n1 = prevleaknode; 80 | prevleaknode = n2; 81 | 82 | if (!n1) 83 | return; 84 | 85 | VectorCopy (n2->winding->points[0], p1); 86 | for (i=1 ; i< n2->winding->numpoints ; i++) 87 | { 88 | for (j=0 ; j<3 ; j++) 89 | p1[j] = (p1[j] + n2->winding->points[i][j]) / 2; 90 | } 91 | 92 | VectorCopy (n1->winding->points[0], p2); 93 | for (i=1 ; i< n1->winding->numpoints ; i++) 94 | { 95 | for (j=0 ; j<3 ; j++) 96 | p2[j] = (p2[j] + n1->winding->points[i][j]) / 2; 97 | } 98 | 99 | VectorSubtract (p2, p1, dir); 100 | len = VectorLength (dir); 101 | VectorNormalize (dir); 102 | 103 | while (len > 2) 104 | { 105 | fprintf (leakfile,"%f %f %f\n", p1[0], p1[1], p1[2]); 106 | for (i=0 ; i<3 ; i++) 107 | p1[i] += dir[i]*2; 108 | len -= 2; 109 | } 110 | } 111 | 112 | /* 113 | ================== 114 | RecursiveFillOutside 115 | 116 | If fill is false, just check, don't fill 117 | Returns true if an occupied leaf is reached 118 | ================== 119 | */ 120 | int hit_occupied; 121 | int backdraw; 122 | qboolean RecursiveFillOutside (node_t *l, qboolean fill) 123 | { 124 | portal_t *p; 125 | int s; 126 | 127 | if (l->contents == CONTENTS_SOLID || l->contents == CONTENTS_SKY) 128 | return false; 129 | 130 | if (l->valid == valid) 131 | return false; 132 | 133 | if (l->occupied) 134 | return true; 135 | 136 | l->valid = valid; 137 | 138 | // fill it and it's neighbors 139 | if (fill) 140 | l->contents = CONTENTS_SOLID; 141 | outleafs++; 142 | 143 | for (p=l->portals ; p ; ) 144 | { 145 | s = (p->nodes[0] == l); 146 | 147 | if (RecursiveFillOutside (p->nodes[s], fill) ) 148 | { // leaked, so stop filling 149 | if (backdraw-- > 0) 150 | { 151 | MarkLeakTrail (p); 152 | DrawLeaf (l, 2); 153 | } 154 | return true; 155 | } 156 | p = p->next[!s]; 157 | } 158 | 159 | return false; 160 | } 161 | 162 | /* 163 | ================== 164 | ClearOutFaces 165 | 166 | ================== 167 | */ 168 | void ClearOutFaces (node_t *node) 169 | { 170 | face_t **fp; 171 | 172 | if (node->planenum != -1) 173 | { 174 | ClearOutFaces (node->children[0]); 175 | ClearOutFaces (node->children[1]); 176 | return; 177 | } 178 | if (node->contents != CONTENTS_SOLID) 179 | return; 180 | 181 | for (fp=node->markfaces ; *fp ; fp++) 182 | { 183 | // mark all the original faces that are removed 184 | (*fp)->numpoints = 0; 185 | } 186 | node->faces = NULL; 187 | } 188 | 189 | 190 | //============================================================================= 191 | 192 | /* 193 | =========== 194 | FillOutside 195 | 196 | =========== 197 | */ 198 | qboolean FillOutside (node_t *node) 199 | { 200 | int s; 201 | vec_t *v; 202 | int i; 203 | qboolean inside; 204 | 205 | qprintf ("----- FillOutside ----\n"); 206 | 207 | if (nofill) 208 | { 209 | printf ("skipped\n"); 210 | return false; 211 | } 212 | 213 | inside = false; 214 | for (i=1 ; inodes[1] == &outside_node); 230 | 231 | // first check to see if an occupied leaf is hit 232 | outleafs = 0; 233 | valid++; 234 | 235 | prevleaknode = NULL; 236 | 237 | if (!hullnum) 238 | { 239 | leakfile = fopen (pointfilename, "w"); 240 | if (!leakfile) 241 | Error ("Couldn't open %s\n", pointfilename); 242 | } 243 | 244 | if (RecursiveFillOutside (outside_node.portals->nodes[s], false)) 245 | { 246 | v = entities[hit_occupied].origin; 247 | qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); 248 | qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n" 249 | , v[0], v[1], v[2]); 250 | qprintf ("no filling performed\n"); 251 | if (!hullnum) 252 | fclose (leakfile); 253 | qprintf ("leak file written to %s\n", pointfilename); 254 | qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); 255 | return false; 256 | } 257 | if (!hullnum) 258 | fclose (leakfile); 259 | 260 | // now go back and fill things in 261 | valid++; 262 | RecursiveFillOutside (outside_node.portals->nodes[s], true); 263 | 264 | // remove faces from filled in leafs 265 | ClearOutFaces (node); 266 | 267 | qprintf ("%4i outleafs\n", outleafs); 268 | return true; 269 | } 270 | 271 | 272 | -------------------------------------------------------------------------------- /common/bspfile.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | 22 | // upper design bounds 23 | 24 | #define MAX_MAP_HULLS 4 25 | 26 | #define MAX_MAP_MODELS 256 27 | #define MAX_MAP_BRUSHES 4096 28 | #define MAX_MAP_ENTITIES 1024 29 | #define MAX_MAP_ENTSTRING 65536 30 | 31 | #define MAX_MAP_PLANES 8192 32 | #define MAX_MAP_NODES 32767 // because negative shorts are contents 33 | #define MAX_MAP_CLIPNODES 32767 // 34 | #define MAX_MAP_LEAFS 32767 // 35 | #define MAX_MAP_VERTS 65535 36 | #define MAX_MAP_FACES 65535 37 | #define MAX_MAP_MARKSURFACES 65535 38 | #define MAX_MAP_TEXINFO 4096 39 | #define MAX_MAP_EDGES 256000 40 | #define MAX_MAP_SURFEDGES 512000 41 | #define MAX_MAP_MIPTEX 0x200000 42 | #define MAX_MAP_LIGHTING 0x100000 43 | #define MAX_MAP_VISIBILITY 0x100000 44 | 45 | // key / value pair sizes 46 | 47 | #define MAX_KEY 32 48 | #define MAX_VALUE 1024 49 | 50 | //============================================================================= 51 | 52 | 53 | #define BSPVERSION 29 54 | 55 | typedef struct 56 | { 57 | int fileofs, filelen; 58 | } lump_t; 59 | 60 | #define LUMP_ENTITIES 0 61 | #define LUMP_PLANES 1 62 | #define LUMP_TEXTURES 2 63 | #define LUMP_VERTEXES 3 64 | #define LUMP_VISIBILITY 4 65 | #define LUMP_NODES 5 66 | #define LUMP_TEXINFO 6 67 | #define LUMP_FACES 7 68 | #define LUMP_LIGHTING 8 69 | #define LUMP_CLIPNODES 9 70 | #define LUMP_LEAFS 10 71 | #define LUMP_MARKSURFACES 11 72 | #define LUMP_EDGES 12 73 | #define LUMP_SURFEDGES 13 74 | #define LUMP_MODELS 14 75 | 76 | #define HEADER_LUMPS 15 77 | 78 | typedef struct 79 | { 80 | float mins[3], maxs[3]; 81 | float origin[3]; 82 | int headnode[MAX_MAP_HULLS]; 83 | int visleafs; // not including the solid leaf 0 84 | int firstface, numfaces; 85 | } dmodel_t; 86 | 87 | typedef struct 88 | { 89 | int version; 90 | lump_t lumps[HEADER_LUMPS]; 91 | } dheader_t; 92 | 93 | typedef struct 94 | { 95 | int nummiptex; 96 | int dataofs[4]; // [nummiptex] 97 | } dmiptexlump_t; 98 | 99 | #define MIPLEVELS 4 100 | typedef struct miptex_s 101 | { 102 | char name[16]; 103 | unsigned width, height; 104 | unsigned offsets[MIPLEVELS]; // four mip maps stored 105 | } miptex_t; 106 | 107 | 108 | typedef struct 109 | { 110 | float point[3]; 111 | } dvertex_t; 112 | 113 | 114 | // 0-2 are axial planes 115 | #define PLANE_X 0 116 | #define PLANE_Y 1 117 | #define PLANE_Z 2 118 | 119 | // 3-5 are non-axial planes snapped to the nearest 120 | #define PLANE_ANYX 3 121 | #define PLANE_ANYY 4 122 | #define PLANE_ANYZ 5 123 | 124 | typedef struct 125 | { 126 | float normal[3]; 127 | float dist; 128 | int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate 129 | } dplane_t; 130 | 131 | 132 | 133 | #define CONTENTS_EMPTY -1 134 | #define CONTENTS_SOLID -2 135 | #define CONTENTS_WATER -3 136 | #define CONTENTS_SLIME -4 137 | #define CONTENTS_LAVA -5 138 | #define CONTENTS_SKY -6 139 | 140 | // !!! if this is changed, it must be changed in asm_i386.h too !!! 141 | typedef struct 142 | { 143 | int planenum; 144 | short children[2]; // negative numbers are -(leafs+1), not nodes 145 | short mins[3]; // for sphere culling 146 | short maxs[3]; 147 | unsigned short firstface; 148 | unsigned short numfaces; // counting both sides 149 | } dnode_t; 150 | 151 | typedef struct 152 | { 153 | int planenum; 154 | short children[2]; // negative numbers are contents 155 | } dclipnode_t; 156 | 157 | 158 | typedef struct texinfo_s 159 | { 160 | float vecs[2][4]; // [s/t][xyz offset] 161 | int miptex; 162 | int flags; 163 | } texinfo_t; 164 | #define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision 165 | 166 | // note that edge 0 is never used, because negative edge nums are used for 167 | // counterclockwise use of the edge in a face 168 | typedef struct 169 | { 170 | unsigned short v[2]; // vertex numbers 171 | } dedge_t; 172 | 173 | #define MAXLIGHTMAPS 4 174 | typedef struct 175 | { 176 | short planenum; 177 | short side; 178 | 179 | int firstedge; // we must support > 64k edges 180 | short numedges; 181 | short texinfo; 182 | 183 | // lighting info 184 | byte styles[MAXLIGHTMAPS]; 185 | int lightofs; // start of [numstyles*surfsize] samples 186 | } dface_t; 187 | 188 | 189 | 190 | #define AMBIENT_WATER 0 191 | #define AMBIENT_SKY 1 192 | #define AMBIENT_SLIME 2 193 | #define AMBIENT_LAVA 3 194 | 195 | #define NUM_AMBIENTS 4 // automatic ambient sounds 196 | 197 | // leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas 198 | // all other leafs need visibility info 199 | typedef struct 200 | { 201 | int contents; 202 | int visofs; // -1 = no visibility info 203 | 204 | short mins[3]; // for frustum culling 205 | short maxs[3]; 206 | 207 | unsigned short firstmarksurface; 208 | unsigned short nummarksurfaces; 209 | 210 | byte ambient_level[NUM_AMBIENTS]; 211 | } dleaf_t; 212 | 213 | //============================================================================ 214 | 215 | #ifndef QUAKE_GAME 216 | 217 | // the utilities get to be lazy and just use large static arrays 218 | 219 | extern int nummodels; 220 | extern dmodel_t dmodels[MAX_MAP_MODELS]; 221 | 222 | extern int visdatasize; 223 | extern byte dvisdata[MAX_MAP_VISIBILITY]; 224 | 225 | extern int lightdatasize; 226 | extern byte dlightdata[MAX_MAP_LIGHTING]; 227 | 228 | extern int texdatasize; 229 | extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t) 230 | 231 | extern int entdatasize; 232 | extern char dentdata[MAX_MAP_ENTSTRING]; 233 | 234 | extern int numleafs; 235 | extern dleaf_t dleafs[MAX_MAP_LEAFS]; 236 | 237 | extern int numplanes; 238 | extern dplane_t dplanes[MAX_MAP_PLANES]; 239 | 240 | extern int numvertexes; 241 | extern dvertex_t dvertexes[MAX_MAP_VERTS]; 242 | 243 | extern int numnodes; 244 | extern dnode_t dnodes[MAX_MAP_NODES]; 245 | 246 | extern int numtexinfo; 247 | extern texinfo_t texinfo[MAX_MAP_TEXINFO]; 248 | 249 | extern int numfaces; 250 | extern dface_t dfaces[MAX_MAP_FACES]; 251 | 252 | extern int numclipnodes; 253 | extern dclipnode_t dclipnodes[MAX_MAP_CLIPNODES]; 254 | 255 | extern int numedges; 256 | extern dedge_t dedges[MAX_MAP_EDGES]; 257 | 258 | extern int nummarksurfaces; 259 | extern unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES]; 260 | 261 | extern int numsurfedges; 262 | extern int dsurfedges[MAX_MAP_SURFEDGES]; 263 | 264 | 265 | 266 | void LoadBSPFile (char *filename); 267 | void WriteBSPFile (char *filename); 268 | void PrintBSPFileSizes (void); 269 | 270 | #endif 271 | -------------------------------------------------------------------------------- /qbsp/merge.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // merge.c 21 | 22 | #include "bsp5.h" 23 | 24 | 25 | #define CONTINUOUS_EPSILON 0.001 26 | 27 | /* 28 | ================ 29 | CheckColinear 30 | 31 | ================ 32 | */ 33 | void CheckColinear (face_t *f) 34 | { 35 | int i, j; 36 | vec3_t v1, v2; 37 | 38 | for (i=0 ; inumpoints ;i++) 39 | { 40 | // skip the point if the vector from the previous point is the same 41 | // as the vector to the next point 42 | j = (i - 1 < 0) ? f->numpoints - 1 : i - 1; 43 | VectorSubtract (f->pts[i], f->pts[j], v1); 44 | VectorNormalize (v1); 45 | 46 | j = (i + 1 == f->numpoints) ? 0 : i + 1; 47 | VectorSubtract (f->pts[j], f->pts[i], v2); 48 | VectorNormalize (v2); 49 | 50 | if (VectorCompare (v1, v2)) 51 | Error ("Colinear edge"); 52 | } 53 | 54 | } 55 | 56 | 57 | /* 58 | ============= 59 | TryMerge 60 | 61 | If two polygons share a common edge and the edges that meet at the 62 | common points are both inside the other polygons, merge them 63 | 64 | Returns NULL if the faces couldn't be merged, or the new face. 65 | The originals will NOT be freed. 66 | ============= 67 | */ 68 | face_t *TryMerge (face_t *f1, face_t *f2) 69 | { 70 | vec_t *p1, *p2, *p3, *p4, *back; 71 | face_t *newf; 72 | int i, j, k, l; 73 | vec3_t normal, delta, planenormal; 74 | vec_t dot; 75 | plane_t *plane; 76 | qboolean keep1, keep2; 77 | 78 | if (f1->numpoints == -1 || f2->numpoints == -1) 79 | return NULL; 80 | if (f1->planeside != f2->planeside) 81 | return NULL; 82 | if (f1->texturenum != f2->texturenum) 83 | return NULL; 84 | if (f1->contents[0] != f2->contents[0]) 85 | return NULL; 86 | if (f1->contents[1] != f2->contents[1]) 87 | return NULL; 88 | 89 | // 90 | // find a common edge 91 | // 92 | p1 = p2 = NULL; // stop compiler warning 93 | j = 0; // 94 | 95 | for (i=0 ; inumpoints ; i++) 96 | { 97 | p1 = f1->pts[i]; 98 | p2 = f1->pts[(i+1)%f1->numpoints]; 99 | for (j=0 ; jnumpoints ; j++) 100 | { 101 | p3 = f2->pts[j]; 102 | p4 = f2->pts[(j+1)%f2->numpoints]; 103 | for (k=0 ; k<3 ; k++) 104 | { 105 | if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON) 106 | break; 107 | if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON) 108 | break; 109 | } 110 | if (k==3) 111 | break; 112 | } 113 | if (j < f2->numpoints) 114 | break; 115 | } 116 | 117 | if (i == f1->numpoints) 118 | return NULL; // no matching edges 119 | 120 | // 121 | // check slope of connected lines 122 | // if the slopes are colinear, the point can be removed 123 | // 124 | plane = &planes[f1->planenum]; 125 | VectorCopy (plane->normal, planenormal); 126 | if (f1->planeside) 127 | VectorSubtract (vec3_origin, planenormal, planenormal); 128 | 129 | back = f1->pts[(i+f1->numpoints-1)%f1->numpoints]; 130 | VectorSubtract (p1, back, delta); 131 | CrossProduct (planenormal, delta, normal); 132 | VectorNormalize (normal); 133 | 134 | back = f2->pts[(j+2)%f2->numpoints]; 135 | VectorSubtract (back, p1, delta); 136 | dot = DotProduct (delta, normal); 137 | if (dot > CONTINUOUS_EPSILON) 138 | return NULL; // not a convex polygon 139 | keep1 = dot < -CONTINUOUS_EPSILON; 140 | 141 | back = f1->pts[(i+2)%f1->numpoints]; 142 | VectorSubtract (back, p2, delta); 143 | CrossProduct (planenormal, delta, normal); 144 | VectorNormalize (normal); 145 | 146 | back = f2->pts[(j+f2->numpoints-1)%f2->numpoints]; 147 | VectorSubtract (back, p2, delta); 148 | dot = DotProduct (delta, normal); 149 | if (dot > CONTINUOUS_EPSILON) 150 | return NULL; // not a convex polygon 151 | keep2 = dot < -CONTINUOUS_EPSILON; 152 | 153 | // 154 | // build the new polygon 155 | // 156 | if (f1->numpoints + f2->numpoints > MAXEDGES) 157 | { 158 | // Error ("TryMerge: too many edges!"); 159 | return NULL; 160 | } 161 | 162 | newf = NewFaceFromFace (f1); 163 | 164 | // copy first polygon 165 | for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints) 166 | { 167 | if (k==(i+1)%f1->numpoints && !keep2) 168 | continue; 169 | 170 | VectorCopy (f1->pts[k], newf->pts[newf->numpoints]); 171 | newf->numpoints++; 172 | } 173 | 174 | // copy second polygon 175 | for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints) 176 | { 177 | if (l==(j+1)%f2->numpoints && !keep1) 178 | continue; 179 | VectorCopy (f2->pts[l], newf->pts[newf->numpoints]); 180 | newf->numpoints++; 181 | } 182 | 183 | return newf; 184 | } 185 | 186 | 187 | /* 188 | =============== 189 | MergeFaceToList 190 | =============== 191 | */ 192 | qboolean mergedebug; 193 | face_t *MergeFaceToList (face_t *face, face_t *list) 194 | { 195 | face_t *newf, *f; 196 | 197 | for (f=list ; f ; f=f->next) 198 | { 199 | //CheckColinear (f); 200 | if (mergedebug) 201 | { 202 | Draw_ClearWindow (); 203 | Draw_DrawFace (face); 204 | Draw_DrawFace (f); 205 | Draw_SetBlack (); 206 | } 207 | newf = TryMerge (face, f); 208 | if (!newf) 209 | continue; 210 | FreeFace (face); 211 | f->numpoints = -1; // merged out 212 | return MergeFaceToList (newf, list); 213 | } 214 | 215 | // didn't merge, so add at start 216 | face->next = list; 217 | return face; 218 | } 219 | 220 | 221 | /* 222 | =============== 223 | FreeMergeListScraps 224 | =============== 225 | */ 226 | face_t *FreeMergeListScraps (face_t *merged) 227 | { 228 | face_t *head, *next; 229 | 230 | head = NULL; 231 | for ( ; merged ; merged = next) 232 | { 233 | next = merged->next; 234 | if (merged->numpoints == -1) 235 | FreeFace (merged); 236 | else 237 | { 238 | merged->next = head; 239 | head = merged; 240 | } 241 | } 242 | 243 | return head; 244 | } 245 | 246 | 247 | /* 248 | =============== 249 | MergePlaneFaces 250 | =============== 251 | */ 252 | void MergePlaneFaces (surface_t *plane) 253 | { 254 | face_t *f1, *next; 255 | face_t *merged; 256 | 257 | merged = NULL; 258 | 259 | for (f1 = plane->faces ; f1 ; f1 = next) 260 | { 261 | next = f1->next; 262 | merged = MergeFaceToList (f1, merged); 263 | } 264 | 265 | // chain all of the non-empty faces to the plane 266 | plane->faces = FreeMergeListScraps (merged); 267 | } 268 | 269 | 270 | /* 271 | ============ 272 | MergeAll 273 | ============ 274 | */ 275 | void MergeAll (surface_t *surfhead) 276 | { 277 | surface_t *surf; 278 | int mergefaces; 279 | face_t *f; 280 | 281 | printf ("---- MergeAll ----\n"); 282 | 283 | mergefaces = 0; 284 | for (surf = surfhead ; surf ; surf=surf->next) 285 | { 286 | MergePlaneFaces (surf); 287 | Draw_ClearWindow (); 288 | for (f=surf->faces ; f ; f=f->next) 289 | { 290 | Draw_DrawFace (f); 291 | mergefaces++; 292 | } 293 | } 294 | 295 | printf ("%i mergefaces\n", mergefaces); 296 | } 297 | -------------------------------------------------------------------------------- /qc/subs.qc: -------------------------------------------------------------------------------- 1 | /* 2 | subs.qc 3 | 4 | sub-functions, mostly movement related 5 | 6 | Copyright (C) 1996-1997 Id Software, Inc. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 | 17 | See the GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to: 21 | 22 | Free Software Foundation, Inc. 23 | 59 Temple Place - Suite 330 24 | Boston, MA 02111-1307, USA 25 | 26 | */ 27 | 28 | 29 | void() SUB_Null = {}; 30 | 31 | void() SUB_Remove = {remove(self);}; 32 | 33 | 34 | /* 35 | QuakeEd only writes a single float for angles (bad idea), so up and down are 36 | just constant angles. 37 | */ 38 | vector() SetMovedir = 39 | { 40 | if (self.angles == '0 -1 0') 41 | self.movedir = '0 0 1'; 42 | else if (self.angles == '0 -2 0') 43 | self.movedir = '0 0 -1'; 44 | else 45 | { 46 | makevectors (self.angles); 47 | self.movedir = v_forward; 48 | } 49 | 50 | self.angles = '0 0 0'; 51 | }; 52 | 53 | /* 54 | ================ 55 | InitTrigger 56 | ================ 57 | */ 58 | void() InitTrigger = 59 | { 60 | // trigger angles are used for one-way touches. An angle of 0 is assumed 61 | // to mean no restrictions, so use a yaw of 360 instead. 62 | if (self.angles != '0 0 0') 63 | SetMovedir (); 64 | self.solid = SOLID_TRIGGER; 65 | setmodel (self, self.model); // set size and link into world 66 | self.movetype = MOVETYPE_NONE; 67 | self.modelindex = 0; 68 | self.model = ""; 69 | }; 70 | 71 | /* 72 | ============= 73 | SUB_CalcMove 74 | 75 | calculate self.velocity and self.nextthink to reach dest from 76 | self.origin traveling at speed 77 | =============== 78 | */ 79 | void(entity ent, vector tdest, float tspeed, void() func) SUB_CalcMoveEnt = 80 | { 81 | local entity stemp; 82 | stemp = self; 83 | self = ent; 84 | 85 | SUB_CalcMove (tdest, tspeed, func); 86 | self = stemp; 87 | }; 88 | 89 | void(vector tdest, float tspeed, void() func) SUB_CalcMove = 90 | { 91 | local vector vdestdelta; 92 | local float len, traveltime; 93 | 94 | if (!tspeed) 95 | objerror("No speed is defined!"); 96 | 97 | self.think1 = func; 98 | self.finaldest = tdest; 99 | self.think = SUB_CalcMoveDone; 100 | 101 | if (tdest == self.origin) 102 | { 103 | self.velocity = '0 0 0'; 104 | self.nextthink = self.ltime + 0.1; 105 | return; 106 | } 107 | 108 | // set destdelta to the vector needed to move 109 | vdestdelta = tdest - self.origin; 110 | 111 | // calculate length of vector 112 | len = vlen (vdestdelta); 113 | 114 | // divide by speed to get time to reach dest 115 | traveltime = len / tspeed; 116 | 117 | if (traveltime < 0.03) 118 | traveltime = 0.03; 119 | 120 | // set nextthink to trigger a think when dest is reached 121 | self.nextthink = self.ltime + traveltime; 122 | 123 | // scale the destdelta vector by the time spent traveling to get velocity 124 | self.velocity = vdestdelta * (1/traveltime); // qcc won't take vec/float 125 | }; 126 | 127 | /* 128 | ============ 129 | After moving, set origin to exact final destination 130 | ============ 131 | */ 132 | void() SUB_CalcMoveDone = 133 | { 134 | setorigin(self, self.finaldest); 135 | self.velocity = '0 0 0'; 136 | self.nextthink = -1; 137 | if (self.think1) 138 | self.think1(); 139 | }; 140 | 141 | 142 | /* 143 | ============= 144 | SUB_CalcAngleMove 145 | 146 | calculate self.avelocity and self.nextthink to reach destangle from 147 | self.angles rotating 148 | 149 | The calling function should make sure self.think is valid 150 | =============== 151 | */ 152 | void(entity ent, vector destangle, float tspeed, void() func) SUB_CalcAngleMoveEnt = 153 | { 154 | local entity stemp; 155 | stemp = self; 156 | self = ent; 157 | SUB_CalcAngleMove (destangle, tspeed, func); 158 | self = stemp; 159 | }; 160 | 161 | void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove = 162 | { 163 | local vector destdelta; 164 | local float len, traveltime; 165 | 166 | if (!tspeed) 167 | objerror("No speed is defined!"); 168 | 169 | // set destdelta to the vector needed to move 170 | destdelta = destangle - self.angles; 171 | 172 | // calculate length of vector 173 | len = vlen (destdelta); 174 | 175 | // divide by speed to get time to reach dest 176 | traveltime = len / tspeed; 177 | 178 | // set nextthink to trigger a think when dest is reached 179 | self.nextthink = self.ltime + traveltime; 180 | 181 | // scale the destdelta vector by the time spent traveling to get velocity 182 | self.avelocity = destdelta * (1 / traveltime); 183 | 184 | self.think1 = func; 185 | self.finalangle = destangle; 186 | self.think = SUB_CalcAngleMoveDone; 187 | }; 188 | 189 | /* 190 | ============ 191 | After rotating, set angle to exact final angle 192 | ============ 193 | */ 194 | void() SUB_CalcAngleMoveDone = 195 | { 196 | self.angles = self.finalangle; 197 | self.avelocity = '0 0 0'; 198 | self.nextthink = -1; 199 | if (self.think1) 200 | self.think1(); 201 | }; 202 | 203 | 204 | //============================================================================= 205 | 206 | void() DelayThink = 207 | { 208 | activator = self.enemy; 209 | SUB_UseTargets (); 210 | remove(self); 211 | }; 212 | 213 | /* 214 | ============================== 215 | SUB_UseTargets 216 | 217 | the global "activator" should be set to the entity that initiated the firing. 218 | 219 | If self.delay is set, a DelayedUse entity will be created that will actually 220 | do the SUB_UseTargets after that many seconds have passed. 221 | 222 | Centerprints any self.message to the activator. 223 | 224 | Removes all entities with a targetname that match self.killtarget, 225 | and removes them, so some events can remove other triggers. 226 | 227 | Search for (string)targetname in all entities that 228 | match (string)self.target and call their .use function 229 | 230 | ============================== 231 | */ 232 | void() SUB_UseTargets = 233 | { 234 | local entity t, stemp, otemp, act; 235 | 236 | // 237 | // check for a delay 238 | // 239 | if (self.delay) 240 | { 241 | // create a temp object to fire at a later time 242 | t = spawn(); 243 | t.classname = "DelayedUse"; 244 | t.nextthink = time + self.delay; 245 | t.think = DelayThink; 246 | t.enemy = activator; 247 | t.message = self.message; 248 | t.killtarget = self.killtarget; 249 | t.target = self.target; 250 | return; 251 | } 252 | 253 | 254 | // 255 | // print the message 256 | // 257 | if (activator.classname == "player" && self.message != "") 258 | { 259 | centerprint (activator, self.message); 260 | if (!self.noise) 261 | sound (activator, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM); 262 | } 263 | 264 | // 265 | // kill the killtagets 266 | // 267 | if (self.killtarget) 268 | { 269 | t = world; 270 | do 271 | { 272 | t = find (t, targetname, self.killtarget); 273 | if (!t) 274 | return; 275 | remove (t); 276 | } while ( 1 ); 277 | } 278 | 279 | // 280 | // fire targets 281 | // 282 | if (self.target) 283 | { 284 | act = activator; 285 | t = world; 286 | do 287 | { 288 | t = find (t, targetname, self.target); 289 | if (!t) 290 | { 291 | return; 292 | } 293 | stemp = self; 294 | otemp = other; 295 | self = t; 296 | other = stemp; 297 | if (self.use != SUB_Null) 298 | { 299 | if (self.use) 300 | self.use (); 301 | } 302 | self = stemp; 303 | other = otemp; 304 | activator = act; 305 | } while ( 1 ); 306 | } 307 | 308 | 309 | }; 310 | 311 | -------------------------------------------------------------------------------- /common/wadlib.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // wad2lib.c 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | //#include 30 | #include 31 | 32 | #ifdef NeXT 33 | #include 34 | #endif 35 | #include "cmdlib.h" 36 | #include "wadlib.h" 37 | 38 | /* 39 | ============================================================================ 40 | 41 | WAD READING 42 | 43 | ============================================================================ 44 | */ 45 | 46 | 47 | lumpinfo_t *lumpinfo; // location of each lump on disk 48 | int numlumps; 49 | 50 | wadinfo_t header; 51 | FILE *wadhandle; 52 | 53 | 54 | /* 55 | ==================== 56 | W_OpenWad 57 | ==================== 58 | */ 59 | void W_OpenWad (char *filename) 60 | { 61 | lumpinfo_t *lump_p; 62 | unsigned i; 63 | int length; 64 | 65 | // 66 | // open the file and add to directory 67 | // 68 | wadhandle = SafeOpenRead (filename); 69 | SafeRead (wadhandle, &header, sizeof(header)); 70 | 71 | if (strncmp(header.identification,"WAD2",4)) 72 | Error ("Wad file %s doesn't have WAD2 id\n",filename); 73 | 74 | header.numlumps = LittleLong(header.numlumps); 75 | header.infotableofs = LittleLong(header.infotableofs); 76 | 77 | numlumps = header.numlumps; 78 | 79 | length = numlumps*sizeof(lumpinfo_t); 80 | lumpinfo = malloc (length); 81 | lump_p = lumpinfo; 82 | 83 | fseek (wadhandle, header.infotableofs, SEEK_SET); 84 | SafeRead (wadhandle, lumpinfo, length); 85 | 86 | // 87 | // Fill in lumpinfo 88 | // 89 | 90 | for (i=0 ; ifilepos = LittleLong(lump_p->filepos); 93 | lump_p->size = LittleLong(lump_p->size); 94 | } 95 | } 96 | 97 | 98 | 99 | void CleanupName (char *in, char *out) 100 | { 101 | int i; 102 | 103 | for (i=0 ; iname ) ; i++ ) 104 | { 105 | if (!in[i]) 106 | break; 107 | 108 | out[i] = toupper(in[i]); 109 | } 110 | 111 | for ( ; iname ); i++ ) 112 | out[i] = 0; 113 | } 114 | 115 | 116 | /* 117 | ==================== 118 | W_CheckNumForName 119 | 120 | Returns -1 if name not found 121 | ==================== 122 | */ 123 | int W_CheckNumForName (char *name) 124 | { 125 | char cleanname[16]; 126 | int v1,v2, v3, v4; 127 | int i; 128 | lumpinfo_t *lump_p; 129 | 130 | CleanupName (name, cleanname); 131 | 132 | // make the name into four integers for easy compares 133 | 134 | v1 = *(int *)cleanname; 135 | v2 = *(int *)&cleanname[4]; 136 | v3 = *(int *)&cleanname[8]; 137 | v4 = *(int *)&cleanname[12]; 138 | 139 | // find it 140 | 141 | lump_p = lumpinfo; 142 | for (i=0 ; iname == v1 145 | && *(int *)&lump_p->name[4] == v2 146 | && *(int *)&lump_p->name[8] == v3 147 | && *(int *)&lump_p->name[12] == v4) 148 | return i; 149 | } 150 | 151 | return -1; 152 | } 153 | 154 | 155 | /* 156 | ==================== 157 | W_GetNumForName 158 | 159 | Calls W_CheckNumForName, but bombs out if not found 160 | ==================== 161 | */ 162 | int W_GetNumForName (char *name) 163 | { 164 | int i; 165 | 166 | i = W_CheckNumForName (name); 167 | if (i != -1) 168 | return i; 169 | 170 | Error ("W_GetNumForName: %s not found!",name); 171 | return -1; 172 | } 173 | 174 | 175 | /* 176 | ==================== 177 | W_LumpLength 178 | 179 | Returns the buffer size needed to load the given lump 180 | ==================== 181 | */ 182 | int W_LumpLength (int lump) 183 | { 184 | if (lump >= numlumps) 185 | Error ("W_LumpLength: %i >= numlumps",lump); 186 | return lumpinfo[lump].size; 187 | } 188 | 189 | 190 | /* 191 | ==================== 192 | W_ReadLumpNum 193 | 194 | Loads the lump into the given buffer, which must be >= W_LumpLength() 195 | ==================== 196 | */ 197 | void W_ReadLumpNum (int lump, void *dest) 198 | { 199 | lumpinfo_t *l; 200 | 201 | if (lump >= numlumps) 202 | Error ("W_ReadLump: %i >= numlumps",lump); 203 | l = lumpinfo+lump; 204 | 205 | fseek (wadhandle, l->filepos, SEEK_SET); 206 | SafeRead (wadhandle, dest, l->size); 207 | } 208 | 209 | 210 | 211 | /* 212 | ==================== 213 | W_LoadLumpNum 214 | ==================== 215 | */ 216 | void *W_LoadLumpNum (int lump) 217 | { 218 | void *buf; 219 | 220 | if ((unsigned)lump >= numlumps) 221 | Error ("W_CacheLumpNum: %i >= numlumps",lump); 222 | 223 | buf = malloc (W_LumpLength (lump)); 224 | W_ReadLumpNum (lump, buf); 225 | 226 | return buf; 227 | } 228 | 229 | 230 | /* 231 | ==================== 232 | W_LoadLumpName 233 | ==================== 234 | */ 235 | void *W_LoadLumpName (char *name) 236 | { 237 | return W_LoadLumpNum (W_GetNumForName(name)); 238 | } 239 | 240 | 241 | /* 242 | =============================================================================== 243 | 244 | WAD CREATION 245 | 246 | =============================================================================== 247 | */ 248 | 249 | FILE *outwad; 250 | 251 | lumpinfo_t outinfo[4096]; 252 | int outlumps; 253 | 254 | short (*wadshort) (short l); 255 | int (*wadlong) (int l); 256 | 257 | /* 258 | =============== 259 | NewWad 260 | =============== 261 | */ 262 | 263 | void NewWad (char *pathname, qboolean bigendien) 264 | { 265 | outwad = SafeOpenWrite (pathname); 266 | fseek (outwad, sizeof(wadinfo_t), SEEK_SET); 267 | memset (outinfo, 0, sizeof(outinfo)); 268 | 269 | if (bigendien) 270 | { 271 | wadshort = BigShort; 272 | wadlong = BigLong; 273 | } 274 | else 275 | { 276 | wadshort = LittleShort; 277 | wadlong = LittleLong; 278 | } 279 | 280 | outlumps = 0; 281 | } 282 | 283 | 284 | /* 285 | =============== 286 | AddLump 287 | =============== 288 | */ 289 | 290 | void AddLump (char *name, void *buffer, int length, int type, int compress) 291 | { 292 | lumpinfo_t *info; 293 | int ofs; 294 | 295 | info = &outinfo[outlumps]; 296 | outlumps++; 297 | 298 | memset (info,0,sizeof(info)); 299 | 300 | strcpy (info->name, name); 301 | strupr (info->name); 302 | 303 | ofs = ftell(outwad); 304 | info->filepos = wadlong(ofs); 305 | info->size = info->disksize = wadlong(length); 306 | info->type = type; 307 | info->compression = compress; 308 | 309 | // FIXME: do compression 310 | 311 | SafeWrite (outwad, buffer, length); 312 | } 313 | 314 | 315 | /* 316 | =============== 317 | WriteWad 318 | =============== 319 | */ 320 | 321 | void WriteWad (void) 322 | { 323 | wadinfo_t header; 324 | int ofs; 325 | 326 | // write the lumpingo 327 | ofs = ftell(outwad); 328 | 329 | SafeWrite (outwad, outinfo, outlumps*sizeof(lumpinfo_t) ); 330 | 331 | // write the header 332 | 333 | // a program will be able to tell the ednieness of a wad by the id 334 | header.identification[0] = 'W'; 335 | header.identification[1] = 'A'; 336 | header.identification[2] = 'D'; 337 | header.identification[3] = '2'; 338 | 339 | header.numlumps = wadlong(outlumps); 340 | header.infotableofs = wadlong(ofs); 341 | 342 | fseek (outwad, 0, SEEK_SET); 343 | SafeWrite (outwad, &header, sizeof(header)); 344 | fclose (outwad); 345 | } 346 | 347 | 348 | -------------------------------------------------------------------------------- /light/entities.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | // entities.c 21 | 22 | #include "light.h" 23 | 24 | entity_t entities[MAX_MAP_ENTITIES]; 25 | int num_entities; 26 | 27 | /* 28 | ============================================================================== 29 | 30 | ENTITY FILE PARSING 31 | 32 | If a light has a targetname, generate a unique style in the 32-63 range 33 | ============================================================================== 34 | */ 35 | 36 | int numlighttargets; 37 | char lighttargets[32][64]; 38 | 39 | int LightStyleForTargetname (char *targetname, qboolean alloc) 40 | { 41 | int i; 42 | 43 | for (i=0 ; ikey, key); 152 | strcpy (epair->value, com_token); 153 | epair->next = entity->epairs; 154 | entity->epairs = epair; 155 | 156 | if (!strcmp(key, "classname")) 157 | strcpy (entity->classname, com_token); 158 | else if (!strcmp(key, "target")) 159 | strcpy (entity->target, com_token); 160 | else if (!strcmp(key, "targetname")) 161 | strcpy (entity->targetname, com_token); 162 | else if (!strcmp(key, "origin")) 163 | { 164 | // scan into doubles, then assign 165 | // which makes it vec_t size independent 166 | if (sscanf(com_token, "%lf %lf %lf", 167 | &vec[0], &vec[1], &vec[2]) != 3) 168 | Error ("LoadEntities: not 3 values for origin"); 169 | for (i=0 ; i<3 ; i++) 170 | entity->origin[i] = vec[i]; 171 | } 172 | else if (!strncmp(key, "light", 5) || !strcmp (key, "_light") ) 173 | { 174 | entity->light = atof(com_token); 175 | } 176 | else if (!strcmp(key, "style")) 177 | { 178 | entity->style = atof(com_token); 179 | if ((unsigned)entity->style > 254) 180 | Error ("Bad light style %i (must be 0-254)", entity->style); 181 | } 182 | else if (!strcmp(key, "angle")) 183 | { 184 | entity->angle = atof(com_token); 185 | } 186 | 187 | } 188 | 189 | // all fields have been parsed 190 | if (!strncmp (entity->classname, "light", 5) && !entity->light) 191 | entity->light = DEFAULTLIGHTLEVEL; 192 | 193 | if (!strcmp (entity->classname, "light")) 194 | { 195 | if (entity->targetname[0] && !entity->style) 196 | { 197 | char s[16]; 198 | 199 | entity->style = LightStyleForTargetname (entity->targetname, true); 200 | sprintf (s,"%i", entity->style); 201 | SetKeyValue (entity, "style", s); 202 | } 203 | } 204 | } 205 | 206 | printf ("%d entities read\n", num_entities); 207 | 208 | MatchTargets (); 209 | } 210 | 211 | char *ValueForKey (entity_t *ent, char *key) 212 | { 213 | epair_t *ep; 214 | 215 | for (ep=ent->epairs ; ep ; ep=ep->next) 216 | if (!strcmp (ep->key, key) ) 217 | return ep->value; 218 | return ""; 219 | } 220 | 221 | void SetKeyValue (entity_t *ent, char *key, char *value) 222 | { 223 | epair_t *ep; 224 | 225 | for (ep=ent->epairs ; ep ; ep=ep->next) 226 | if (!strcmp (ep->key, key) ) 227 | { 228 | strcpy (ep->value, value); 229 | return; 230 | } 231 | ep = malloc (sizeof(*ep)); 232 | ep->next = ent->epairs; 233 | ent->epairs = ep; 234 | strcpy (ep->key, key); 235 | strcpy (ep->value, value); 236 | } 237 | 238 | float FloatForKey (entity_t *ent, char *key) 239 | { 240 | char *k; 241 | 242 | k = ValueForKey (ent, key); 243 | return atof(k); 244 | } 245 | 246 | void GetVectorForKey (entity_t *ent, char *key, vec3_t vec) 247 | { 248 | char *k; 249 | 250 | k = ValueForKey (ent, key); 251 | sscanf (k, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]); 252 | } 253 | 254 | 255 | 256 | /* 257 | ================ 258 | WriteEntitiesToString 259 | ================ 260 | */ 261 | void WriteEntitiesToString (void) 262 | { 263 | char *buf, *end; 264 | epair_t *ep; 265 | char line[128]; 266 | int i; 267 | 268 | buf = dentdata; 269 | end = buf; 270 | *end = 0; 271 | 272 | printf ("%i switchable light styles\n", numlighttargets); 273 | 274 | for (i=0 ; inext) 284 | { 285 | sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value); 286 | strcat (end, line); 287 | end += strlen(line); 288 | } 289 | strcat (end,"}\n"); 290 | end += 2; 291 | 292 | if (end > buf + MAX_MAP_ENTSTRING) 293 | Error ("Entity text too long"); 294 | } 295 | entdatasize = end - buf + 1; 296 | } 297 | 298 | -------------------------------------------------------------------------------- /comments/text.txt: -------------------------------------------------------------------------------- 1 | Overall the code is painful to read: 2 | 3 | - Very few comments 4 | - Some comments are outdated. 5 | - The internal functionment of some function is determined by global variables. This makes is very difficult to keep track of everything. 6 | - Some function are named in a way that the reader is sent totally in a wrong direction (i.e: GatherNodeFaces actually frees the bsp and 7 | rebuild the surfaces. 8 | 9 | CSG: Constructive Solid Geometry (Technique used in solid modeling. Constructive solid geometry allows a modeler to create a complex surface or object by using Boolean operators to combine objects.) 10 | http://www.flipcode.com/archives/Constructive_Solid_Geometry.shtml 11 | 12 | Good CSG Union stuff 13 | http://mattn.ninex.info/files/MAPFiles.pdf 14 | 15 | Laidlaw and Naylor (BSP based approach) 16 | Laidlaw paper: http://www.cs.brown.edu/research/vis/docs/pdf/Laidlaw-1986-CSG.pdf 17 | 18 | The CSG system relies on a faked OOP system with two objects "inside" in csg4.c and "ouside" in outside.c 19 | 20 | Face splitting against a plane is used all across the board and seems to be seems to be Sutherland-Hodgma inspired. 21 | 22 | QBSP : 23 | ====== 24 | 25 | 26 | Summarized QBSP call tree : 27 | =========================== 28 | 29 | Quake1 MAP format contains entities. The world is described as an entity which is ALWAYS the first entity in the map file. 30 | The world entity can be recognized because it has the key/value: "classname" "worldspawn" 31 | If the first entity in the map file does not have the right classname (worldspawn): This is a faulty file. 32 | 33 | mbrush_t brush_t: 34 | - The map editor delivers volumes as a collection of plan (4 minimun for a Tetrahedron, no upper limit). 35 | - They are read from the MAP file as mbrush_t. 36 | - Plan are clipped against each other in order to generate facelet grouped in brush_t. 37 | surface_t: Volume formed by the facelet are processed further (discarding invisible facelet) and clipping volume against 38 | each other. In the end only a skin remains, made of surface_t, each containing faces. 39 | 40 | mbrush_t (set of plans)--> brush_t (Set of face_t) --> (surface_t) 41 | 42 | Important note: A Surface is not necessarly flat. It is the result of brush volume clipped against each other in order to keep only a visible skin. 43 | Depending on how brushes interact with each other, a surface with many more faces than the brush_t add. 44 | 45 | main() //qbsp.c 46 | { 47 | ProcessFile (sourcename, destname) 48 | { 49 | LoadMapFile 50 | { 51 | | LoadFile //Read text from HardDrive to RAM 52 | | while 53 | | ( ParseEntity () //Read all brushes in an entity. The Quake map in one entity made of thousands of brushes. 54 | | { 55 | | //Read mbrush_t, store result in mapbrushes and add brush to entity's mbrush linked list. 56 | | } 57 | | ) 58 | | 59 | } 60 | 61 | //At this point we have the world entity as an entity_t mbrush 62 | 63 | BeginBSPFile 64 | 65 | CreateHulls 66 | { 67 | ProcessEntity (entnum) 68 | { 69 | //Entity is now a set of mbrush_t 70 | 71 | ent = &entities[entnum]; 72 | 73 | // Intersect all plans in the mbrush_t, generate actual faces and group them in brush_t 74 | bs = Brush_LoadEntity (ent, hullnum); 75 | 76 | //Entity is now a set of brush_t 77 | 78 | // take the brush_ts and clip off all overlapping and contained faces,leaving a perfect skin of the model with no hidden faces 79 | brushset = bs; 80 | surfs = CSGFaces (bs) 81 | 82 | // A Surface is not necessarly flat. It is the result of brush volume clipped against each other in order to keep only 83 | // a visible skin. 84 | 85 | if (entnum == 0 && !nofill) // assume non-world bmodels are simple 86 | { 87 | PortalizeWorld (nodes); 88 | if (FillOutside (nodes)) 89 | { 90 | | FreeAllPortals (nodes); 91 | | 92 | | // get the remaining faces together into surfaces again 93 | | surfs = GatherNodeFaces (nodes); 94 | | 95 | | // merge polygons 96 | | MergeAll (surfs); 97 | | 98 | | // make a really good tree 99 | | nodes = SolidBSP (surfs, false); 100 | | 101 | | // make the real portals for vis tracing 102 | | PortalizeWorld (nodes); 103 | | 104 | | // save portal file for vis tracing 105 | | WritePortalfile (nodes); 106 | | 107 | | // fix tjunctions 108 | | tjunc (nodes); 109 | } 110 | FreeAllPortals (nodes); 111 | } 112 | 113 | WriteNodePlanes (nodes); 114 | MakeFaceEdges (nodes); 115 | 116 | //Write the BSP Nodes. 117 | WriteDrawNodes (nodes); 118 | } 119 | } 120 | ReadClipHull (1) 121 | ReadClipHull (2) 122 | 123 | WriteEntitiesToString 124 | FinishBSPFile 125 | } 126 | } 127 | 128 | 129 | Unrolled QBSP : 130 | =============== 131 | 132 | 133 | 134 | Portal is generated from the optimized BSP tree (optimized mean that the spliting plan was chosen according to the least-split 135 | heurisitc instead of the mid-plan heuristic). 136 | 137 | 138 | Q & A : 139 | ======= 140 | 141 | 1.BSP creation heuristic: 142 | 143 | Choose a surface, its plan is a candidate for becomming the splitting plan. 144 | Chose the plan that will generate the least cut. 145 | 146 | Subdivizion stops when no more surfaces are available. 147 | until all surfaces have been used. In the resulting final BSP leafs contain ONE surface 148 | 149 | When the BSP generator has no more surfaces, it looks at the content of the last splitted surface and set the leaf content. 150 | 151 | Testing proved all this wrong: By tracing I can see that some leafs contain 10 surfaces and 15 faces.....back to reading code: 152 | 153 | 154 | On split, any surface that is right on the splitting plane is marked via onnode and cannot be used as splitting plane later. 155 | 156 | A leaf can contains several surfaces if they are parallel ( the split selector will never chose a face that 157 | split no other polygon). 158 | 159 | 1. PartitionSurfaces recurse until a split plan is NOT returned. SelectPartition controls the recursion. 160 | 161 | 162 | 2. Why does a surface have several faces ?! A surface is supposed to be flat and can contain any number of vertices ? 163 | 164 | 3. What is the average number of portal per leafs ? Per node ? 165 | 4. How is the leaf content determinated ? 166 | 5. When does the BSP building process stops splitting ? 167 | 6. What ends up in the PRT file ? 168 | 7. How is the splitting node chosen ? 169 | 170 | PartitionSurfaces: At each recursion step the intial surface linked list can be changed. surface->next is EXTREMY likely 171 | to have been modified so using it, even for a leaf after the BSP has been built would be a non sense. 172 | 173 | 174 | Portals: It seems leak are an issue because the tool will not be able to determine which part is inside and which part is outside. 175 | Quake1 does not feature aeraportal (brush that modify the portal graph in realtime). https://developer.valvesoftware.com/wiki/Areaportal 176 | A nice explanation about aeraportal leaks (https://developer.valvesoftware.com/wiki/Areaportal). Explain that aeraportal 177 | can loop around itself. 178 | 179 | VIS : 180 | ===== 181 | 182 | 183 | 184 | 185 | 186 | QCC : 187 | ===== 188 | 189 | QuakeC Reference Manual 190 | http://pages.cs.wisc.edu/~jeremyp/quake/quakec/quakec.pdf 191 | 192 | Good tutorial: 193 | 194 | http://www.inside3d.com/showtutorial.php?id=153 195 | http://www.inside3d.com/showtutorial.php?id=154 196 | http://www.inside3d.com/showtutorial.php?id=156 197 | http://www.inside3d.com/showtutorial.php?id=157 198 | 199 | 200 | Looks like the compilation is the same as q3cc: The list of all the files to be compiled is in a file (here name progs.src). 201 | 202 | "progs.src" content : 203 | ===================== 204 | ./qwprogs.dat 205 | 206 | defs.qc 207 | subs.qc 208 | combat.qc 209 | items.qc 210 | weapons.qc 211 | world.qc 212 | client.qc 213 | spectate.qc 214 | player.qc 215 | doors.qc 216 | buttons.qc 217 | triggers.qc 218 | plats.qc 219 | misc.qc 220 | 221 | server.qc 222 | 223 | 224 | Note: qwprogs.dat is the output filename. -------------------------------------------------------------------------------- /qc/combat.qc: -------------------------------------------------------------------------------- 1 | /* 2 | combat.qc 3 | 4 | damage, obit, etc related functions 5 | 6 | Copyright (C) 1996-1997 Id Software, Inc. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 | 17 | See the GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to: 21 | 22 | Free Software Foundation, Inc. 23 | 59 Temple Place - Suite 330 24 | Boston, MA 02111-1307, USA 25 | 26 | */ 27 | 28 | void() T_MissileTouch; 29 | void() info_player_start; 30 | void(entity targ, entity attacker) ClientObituary; 31 | void(entity inflictor, entity attacker, float damage, entity ignore, string dtype) T_RadiusDamage; 32 | 33 | /*SERVER 34 | void() monster_death_use; 35 | */ 36 | 37 | //============================================================================ 38 | 39 | /* 40 | ============ 41 | CanDamage 42 | 43 | Returns true if the inflictor can directly damage the target. Used for 44 | explosions and melee attacks. 45 | ============ 46 | */ 47 | float(entity targ, entity inflictor) CanDamage = 48 | { 49 | // bmodels need special checking because their origin is 0,0,0 50 | if (targ.movetype == MOVETYPE_PUSH) 51 | { 52 | traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self); 53 | if (trace_fraction == 1) 54 | return TRUE; 55 | if (trace_ent == targ) 56 | return TRUE; 57 | return FALSE; 58 | } 59 | 60 | traceline(inflictor.origin, targ.origin, TRUE, self); 61 | if (trace_fraction == 1) 62 | return TRUE; 63 | traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self); 64 | if (trace_fraction == 1) 65 | return TRUE; 66 | traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self); 67 | if (trace_fraction == 1) 68 | return TRUE; 69 | traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self); 70 | if (trace_fraction == 1) 71 | return TRUE; 72 | traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self); 73 | if (trace_fraction == 1) 74 | return TRUE; 75 | 76 | return FALSE; 77 | }; 78 | 79 | 80 | /* 81 | ============ 82 | Killed 83 | ============ 84 | */ 85 | void(entity targ, entity attacker) Killed = 86 | { 87 | local entity oself; 88 | 89 | oself = self; 90 | self = targ; 91 | 92 | if (self.health < -99) 93 | self.health = -99; // don't let sbar look bad if a player 94 | 95 | if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE) 96 | { // doors, triggers, etc 97 | self.th_die (); 98 | self = oself; 99 | return; 100 | } 101 | 102 | self.enemy = attacker; 103 | 104 | // bump the monster counter 105 | if (self.flags & FL_MONSTER) 106 | { 107 | killed_monsters = killed_monsters + 1; 108 | WriteByte (MSG_ALL, SVC_KILLEDMONSTER); 109 | } 110 | 111 | ClientObituary(self, attacker); 112 | 113 | self.takedamage = DAMAGE_NO; 114 | self.touch = SUB_Null; 115 | self.effects = 0; 116 | 117 | /*SERVER 118 | monster_death_use(); 119 | */ 120 | self.th_die (); 121 | 122 | self = oself; 123 | }; 124 | 125 | 126 | /* 127 | ============ 128 | T_Damage 129 | 130 | The damage is coming from inflictor, but get mad at attacker 131 | This should be the only function that ever reduces health. 132 | ============ 133 | */ 134 | void(entity targ, entity inflictor, entity attacker, float damage) T_Damage= 135 | { 136 | local vector dir; 137 | local entity oldself; 138 | local float save; 139 | local float take; 140 | local string s; 141 | local string attackerteam, targteam; 142 | 143 | 144 | if (!targ.takedamage) 145 | return; 146 | 147 | // used by buttons and triggers to set activator for target firing 148 | damage_attacker = attacker; 149 | 150 | 151 | // check for quad damage powerup on the attacker 152 | if (attacker.super_damage_finished > time && inflictor.classname != "door") 153 | if (deathmatch == 4) 154 | damage = damage * 8; 155 | else 156 | damage = damage * 4; 157 | 158 | // save damage based on the target's armor level 159 | 160 | save = ceil(targ.armortype*damage); 161 | if (save >= targ.armorvalue) 162 | { 163 | save = targ.armorvalue; 164 | targ.armortype = 0; // lost all armor 165 | targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)); 166 | } 167 | 168 | targ.armorvalue = targ.armorvalue - save; 169 | take = ceil(damage-save); 170 | 171 | // add to the damage total for clients, which will be sent as a single 172 | // message at the end of the frame 173 | // FIXME: remove after combining shotgun blasts? 174 | if (targ.flags & FL_CLIENT) 175 | { 176 | targ.dmg_take = targ.dmg_take + take; 177 | targ.dmg_save = targ.dmg_save + save; 178 | targ.dmg_inflictor = inflictor; 179 | } 180 | 181 | damage_inflictor = inflictor; 182 | 183 | 184 | // figure momentum add 185 | if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) ) 186 | { 187 | dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5; 188 | dir = normalize(dir); 189 | // Set kickback for smaller weapons 190 | //Zoid -- use normal NQ kickback 191 | // // Read: only if it's not yourself doing the damage 192 | // if ( (damage < 60) & ((attacker.classname == "player") & (targ.classname == "player")) & ( attacker.netname != targ.netname)) 193 | // targ.velocity = targ.velocity + dir * damage * 11; 194 | // else 195 | // Otherwise, these rules apply to rockets and grenades 196 | // for blast velocity 197 | targ.velocity = targ.velocity + dir * damage * 8; 198 | 199 | // Rocket Jump modifiers 200 | if ( (rj > 1) & ((attacker.classname == "player") & (targ.classname == "player")) & ( attacker.netname == targ.netname)) 201 | targ.velocity = targ.velocity + dir * damage * rj; 202 | 203 | } 204 | 205 | 206 | 207 | // check for godmode or invincibility 208 | if (targ.flags & FL_GODMODE) 209 | return; 210 | if (targ.invincible_finished >= time) 211 | { 212 | if (self.invincible_sound < time) 213 | { 214 | sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM); 215 | self.invincible_sound = time + 2; 216 | } 217 | return; 218 | } 219 | 220 | // team play damage avoidance 221 | //ZOID 12-13-96: self.team doesn't work in QW. Use keys 222 | attackerteam = infokey(attacker, "team"); 223 | targteam = infokey(targ, "team"); 224 | 225 | if ((teamplay == 1) && (targteam == attackerteam) && 226 | (attacker.classname == "player") && (attackerteam != "") && 227 | inflictor.classname !="door") 228 | return; 229 | 230 | if ((teamplay == 3) && (targteam == attackerteam) && 231 | (attacker.classname == "player") && (attackerteam != "") && 232 | (targ != attacker)&& inflictor.classname !="door") 233 | return; 234 | 235 | // do the damage 236 | targ.health = targ.health - take; 237 | 238 | if (targ.health <= 0) 239 | { 240 | Killed (targ, attacker); 241 | return; 242 | } 243 | 244 | // react to the damage 245 | oldself = self; 246 | self = targ; 247 | 248 | /*SERVER 249 | if ( (self.flags & FL_MONSTER) && attacker != world) 250 | { 251 | // get mad unless of the same class (except for soldiers) 252 | if (self != attacker && attacker != self.enemy) 253 | { 254 | if ( (self.classname != attacker.classname) 255 | || (self.classname == "monster_army" ) ) 256 | { 257 | if (self.enemy.classname == "player") 258 | self.oldenemy = self.enemy; 259 | self.enemy = attacker; 260 | FoundTarget (); 261 | } 262 | } 263 | } 264 | */ 265 | if (self.th_pain) 266 | { 267 | self.th_pain (attacker, take); 268 | } 269 | 270 | self = oldself; 271 | }; 272 | 273 | /* 274 | ============ 275 | T_RadiusDamage 276 | ============ 277 | */ 278 | void(entity inflictor, entity attacker, float damage, entity ignore, string dtype) T_RadiusDamage = 279 | { 280 | local float points; 281 | local entity head; 282 | local vector org; 283 | 284 | head = findradius(inflictor.origin, damage+40); 285 | 286 | while (head) 287 | { 288 | //bprint (PRINT_HIGH, head.classname); 289 | //bprint (PRINT_HIGH, " | "); 290 | //bprint (PRINT_HIGH, head.netname); 291 | //bprint (PRINT_HIGH, "\n"); 292 | 293 | if (head != ignore) 294 | { 295 | if (head.takedamage) 296 | { 297 | org = head.origin + (head.mins + head.maxs)*0.5; 298 | points = 0.5*vlen (inflictor.origin - org); 299 | if (points < 0) 300 | points = 0; 301 | points = damage - points; 302 | 303 | if (head == attacker) 304 | points = points * 0.5; 305 | if (points > 0) 306 | { 307 | if (CanDamage (head, inflictor)) 308 | { 309 | head.deathtype = dtype; 310 | T_Damage (head, inflictor, attacker, points); 311 | } 312 | } 313 | } 314 | } 315 | head = head.chain; 316 | } 317 | }; 318 | 319 | /* 320 | ============ 321 | T_BeamDamage 322 | ============ 323 | */ 324 | void(entity attacker, float damage) T_BeamDamage = 325 | { 326 | local float points; 327 | local entity head; 328 | 329 | head = findradius(attacker.origin, damage+40); 330 | 331 | while (head) 332 | { 333 | if (head.takedamage) 334 | { 335 | points = 0.5*vlen (attacker.origin - head.origin); 336 | if (points < 0) 337 | points = 0; 338 | points = damage - points; 339 | if (head == attacker) 340 | points = points * 0.5; 341 | if (points > 0) 342 | { 343 | if (CanDamage (head, attacker)) 344 | T_Damage (head, attacker, attacker, points); 345 | } 346 | } 347 | head = head.chain; 348 | } 349 | }; 350 | 351 | -------------------------------------------------------------------------------- /qbsp/bsp5.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | // bsp5.h 22 | 23 | #include "cmdlib.h" 24 | #include "mathlib.h" 25 | #include "bspfile.h" 26 | 27 | typedef struct 28 | { 29 | vec3_t normal; 30 | vec_t dist; 31 | int type; 32 | } plane_t; 33 | 34 | 35 | #include "map.h" 36 | 37 | #define MAX_THREADS 4 38 | 39 | #define ON_EPSILON 0.05 40 | #define BOGUS_RANGE 18000 41 | 42 | // the exact bounding box of the brushes is expanded some for the headnode 43 | // volume. is this still needed? 44 | #define SIDESPACE 24 45 | 46 | //============================================================================ 47 | 48 | 49 | typedef struct 50 | { 51 | int numpoints; 52 | vec3_t points[8]; // variable sized 53 | } winding_t; 54 | 55 | #define MAX_POINTS_ON_WINDING 64 56 | 57 | winding_t *BaseWindingForPlane (plane_t *p); 58 | void CheckWinding (winding_t *w); 59 | winding_t *NewWinding (int points); 60 | void FreeWinding (winding_t *w); 61 | winding_t *CopyWinding (winding_t *w); 62 | winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon); 63 | void DivideWinding (winding_t *in, plane_t *split, winding_t **front, winding_t **back); 64 | 65 | //============================================================================ 66 | 67 | #define MAXEDGES 32 68 | #define MAXPOINTS 28 // don't let a base face get past this 69 | // because it can be split more later 70 | 71 | typedef struct visfacet_s 72 | { 73 | struct visfacet_s *next; 74 | 75 | int planenum; 76 | int planeside; // which side is the front of the face 77 | int texturenum; 78 | int contents[2]; // 0 = front side 79 | 80 | struct visfacet_s *original; // face on node 81 | int outputnumber; // only valid for original faces after 82 | // write surfaces 83 | int numpoints; 84 | vec3_t pts[MAXEDGES]; // FIXME: change to use winding_t 85 | int edges[MAXEDGES]; 86 | } face_t; 87 | 88 | 89 | typedef struct surface_s 90 | { 91 | struct surface_s *next; 92 | struct surface_s *original; // before BSP cuts it up 93 | 94 | int planenum; // FCS: planenum is a reference to a plane_t in 95 | 96 | int outputplanenum; // only valid after WriteSurfacePlanes 97 | vec3_t mins, maxs; 98 | qboolean onnode; // true if surface has already been used 99 | // as a splitting node 100 | face_t *faces; // links to all the faces on either side of the surf 101 | } surface_t; 102 | 103 | 104 | // 105 | // there is a node_t structure for every node and leaf in the bsp tree 106 | // 107 | #define PLANENUM_LEAF -1 108 | 109 | typedef struct node_s 110 | { 111 | vec3_t mins,maxs; // bounding volume, not just points inside 112 | 113 | // information for decision nodes 114 | int planenum; // -1 = leaf node 115 | int outputplanenum; // only valid after WriteNodePlanes 116 | int firstface; // decision node only 117 | int numfaces; // decision node only 118 | struct node_s *children[2]; // only valid for decision nodes 119 | face_t *faces; // decision nodes only, list for both sides 120 | 121 | // information for leafs 122 | int contents; // leaf nodes (0 for decision nodes) 123 | face_t **markfaces; // leaf nodes only, point to node faces //FCS: Original faces 124 | struct portal_s *portals; 125 | int visleafnum; // -1 = solid 126 | int valid; // for flood filling 127 | int occupied; // light number in leaf for outside filling 128 | } node_t; 129 | 130 | //============================================================================= 131 | 132 | // brush.c 133 | 134 | #define NUM_HULLS 2 // normal and +16 135 | 136 | #define NUM_CONTENTS 2 // solid and water 137 | 138 | typedef struct brush_s 139 | { 140 | struct brush_s *next; 141 | vec3_t mins, maxs; 142 | face_t *faces; 143 | int contents; 144 | } brush_t; 145 | 146 | typedef struct 147 | { 148 | vec3_t mins, maxs; 149 | brush_t *brushes; // NULL terminated list 150 | } brushset_t; 151 | 152 | extern int numbrushplanes; 153 | extern plane_t planes[MAX_MAP_PLANES]; 154 | 155 | brushset_t *Brush_LoadEntity (entity_t *ent, int hullnum); 156 | int PlaneTypeForNormal (vec3_t normal); 157 | int FindPlane (plane_t *dplane, int *side); 158 | 159 | //============================================================================= 160 | 161 | // csg4.c 162 | 163 | // build surfaces is also used by GatherNodeFaces 164 | extern face_t *validfaces[MAX_MAP_PLANES]; 165 | surface_t *BuildSurfaces (void); 166 | 167 | face_t *NewFaceFromFace (face_t *in); 168 | surface_t *CSGFaces (brushset_t *bs); 169 | void SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back); 170 | 171 | //============================================================================= 172 | 173 | // solidbsp.c 174 | 175 | void DivideFacet (face_t *in, plane_t *split, face_t **front, face_t **back); 176 | void CalcSurfaceInfo (surface_t *surf); 177 | void SubdivideFace (face_t *f, face_t **prevptr); 178 | node_t *SolidBSP (surface_t *surfhead, qboolean midsplit); 179 | 180 | //============================================================================= 181 | 182 | // merge.c 183 | 184 | void MergePlaneFaces (surface_t *plane); 185 | face_t *MergeFaceToList (face_t *face, face_t *list); 186 | face_t *FreeMergeListScraps (face_t *merged); 187 | void MergeAll (surface_t *surfhead); 188 | 189 | //============================================================================= 190 | 191 | // surfaces.c 192 | 193 | extern int c_cornerverts; 194 | extern int c_tryedges; 195 | extern face_t *edgefaces[MAX_MAP_EDGES][2]; 196 | 197 | extern int firstmodeledge; 198 | extern int firstmodelface; 199 | 200 | void SubdivideFaces (surface_t *surfhead); 201 | 202 | surface_t *GatherNodeFaces (node_t *headnode); 203 | 204 | void MakeFaceEdges (node_t *headnode); 205 | 206 | //============================================================================= 207 | 208 | // portals.c 209 | 210 | typedef struct portal_s 211 | { 212 | int planenum; 213 | node_t *nodes[2]; // [0] = front side of planenum 214 | struct portal_s *next[2]; 215 | winding_t *winding; 216 | } portal_t; 217 | 218 | extern node_t outside_node; // portals outside the world face this 219 | 220 | void PortalizeWorld (node_t *headnode); 221 | void WritePortalfile (node_t *headnode); 222 | void FreeAllPortals (node_t *node); 223 | 224 | //============================================================================= 225 | 226 | // region.c 227 | 228 | void GrowNodeRegions (node_t *headnode); 229 | 230 | //============================================================================= 231 | 232 | // tjunc.c 233 | 234 | void tjunc (node_t *headnode); 235 | 236 | //============================================================================= 237 | 238 | // writebsp.c 239 | 240 | void WriteNodePlanes (node_t *headnode); 241 | void WriteClipNodes (node_t *headnode); 242 | void WriteDrawNodes (node_t *headnode); 243 | 244 | void BumpModel (int hullnum); 245 | int FindFinalPlane (dplane_t *p); 246 | 247 | void BeginBSPFile (void); 248 | void FinishBSPFile (void); 249 | 250 | //============================================================================= 251 | 252 | // draw.c 253 | 254 | void Draw_ClearBounds (void); 255 | void Draw_AddToBounds (vec3_t v); 256 | void Draw_DrawFace (face_t *f); 257 | void Draw_ClearWindow (void); 258 | void Draw_SetRed (void); 259 | void Draw_SetGrey (void); 260 | void Draw_SetBlack (void); 261 | void DrawPoint (vec3_t v); 262 | 263 | void Draw_SetColor (int c); 264 | void SetColor (int c); 265 | void DrawPortal (portal_t *p); 266 | void DrawLeaf (node_t *l, int color); 267 | void DrawBrush (brush_t *b); 268 | 269 | void DrawWinding (winding_t *w); 270 | void DrawTri (vec3_t p1, vec3_t p2, vec3_t p3); 271 | 272 | //============================================================================= 273 | 274 | // outside.c 275 | 276 | qboolean FillOutside (node_t *node); 277 | 278 | //============================================================================= 279 | 280 | extern qboolean drawflag; 281 | extern qboolean nofill; 282 | extern qboolean notjunc; 283 | extern qboolean noclip; 284 | extern qboolean verbose; 285 | 286 | extern int subdivide_size; 287 | 288 | extern int hullnum; 289 | 290 | extern brushset_t *brushset; 291 | 292 | void qprintf (char *fmt, ...); // only prints if verbose 293 | 294 | extern int valid; 295 | 296 | extern char portfilename[1024]; 297 | extern char bspfilename[1024]; 298 | extern char pointfilename[1024]; 299 | 300 | extern qboolean worldmodel; 301 | 302 | 303 | // misc functions 304 | 305 | face_t *AllocFace (void); 306 | void FreeFace (face_t *f); 307 | 308 | struct portal_s *AllocPortal (void); 309 | void FreePortal (struct portal_s *p); 310 | 311 | surface_t *AllocSurface (void); 312 | void FreeSurface (surface_t *s); 313 | 314 | node_t *AllocNode (void); 315 | struct brush_s *AllocBrush (void); 316 | 317 | //============================================================================= 318 | 319 | -------------------------------------------------------------------------------- /common/polylib.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-1997 Id Software, Inc. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | See file, 'COPYING', for details. 18 | */ 19 | 20 | 21 | #include "cmdlib.h" 22 | #include "mathlib.h" 23 | #include "polylib.h" 24 | 25 | #define BOGUS_RANGE 8192 26 | 27 | /* 28 | ============= 29 | AllocWinding 30 | ============= 31 | */ 32 | winding_t *AllocWinding (int points) 33 | { 34 | winding_t *w; 35 | int s; 36 | 37 | s = sizeof(vec_t)*3*points + sizeof(int); 38 | w = malloc (s); 39 | memset (w, 0, s); 40 | return w; 41 | } 42 | 43 | /* 44 | ============ 45 | RemoveColinearPoints 46 | ============ 47 | */ 48 | int c_removed; 49 | 50 | void RemoveColinearPoints (winding_t *w) 51 | { 52 | int i, j, k; 53 | vec3_t v1, v2; 54 | int nump; 55 | vec3_t p[MAX_POINTS_ON_WINDING]; 56 | 57 | nump = 0; 58 | for (i=0 ; inumpoints ; i++) 59 | { 60 | j = (i+1)%w->numpoints; 61 | k = (i+w->numpoints-1)%w->numpoints; 62 | VectorSubtract (w->p[j], w->p[i], v1); 63 | VectorSubtract (w->p[i], w->p[k], v2); 64 | VectorNormalize(v1); 65 | VectorNormalize(v2); 66 | if (DotProduct(v1, v2) < 0.999) 67 | { 68 | VectorCopy (w->p[i], p[nump]); 69 | nump++; 70 | } 71 | } 72 | 73 | if (nump == w->numpoints) 74 | return; 75 | 76 | c_removed += w->numpoints - nump; 77 | w->numpoints = nump; 78 | memcpy (w->p, p, nump*sizeof(p[0])); 79 | } 80 | 81 | /* 82 | ============ 83 | WindingPlane 84 | ============ 85 | */ 86 | void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist) 87 | { 88 | vec3_t v1, v2; 89 | 90 | VectorSubtract (w->p[1], w->p[0], v1); 91 | VectorSubtract (w->p[2], w->p[0], v2); 92 | CrossProduct (v1, v2, normal); 93 | VectorNormalize (normal); 94 | *dist = DotProduct (w->p[0], normal); 95 | 96 | } 97 | 98 | /* 99 | ============= 100 | WindingArea 101 | ============= 102 | */ 103 | vec_t WindingArea (winding_t *w) 104 | { 105 | int i; 106 | vec3_t d1, d2, cross; 107 | vec_t total; 108 | 109 | total = 0; 110 | for (i=2 ; inumpoints ; i++) 111 | { 112 | VectorSubtract (w->p[i-1], w->p[0], d1); 113 | VectorSubtract (w->p[i], w->p[0], d2); 114 | CrossProduct (d1, d2, cross); 115 | total += 0.5 * VectorLength ( cross ); 116 | } 117 | return total; 118 | } 119 | 120 | /* 121 | ============= 122 | WindingCenter 123 | ============= 124 | */ 125 | void WindingCenter (winding_t *w, vec3_t center) 126 | { 127 | int i; 128 | vec3_t d1, d2, cross; 129 | float scale; 130 | 131 | VectorCopy (vec3_origin, center); 132 | for (i=0 ; inumpoints ; i++) 133 | VectorAdd (w->p[i], center, center); 134 | 135 | scale = 1.0/w->numpoints; 136 | VectorScale (center, scale, center); 137 | } 138 | 139 | /* 140 | ================= 141 | BaseWindingForPlane 142 | ================= 143 | */ 144 | winding_t *BaseWindingForPlane (vec3_t normal, float dist) 145 | { 146 | int i, x; 147 | vec_t max, v; 148 | vec3_t org, vright, vup; 149 | winding_t *w; 150 | 151 | // find the major axis 152 | 153 | max = -BOGUS_RANGE; 154 | x = -1; 155 | for (i=0 ; i<3; i++) 156 | { 157 | v = fabs(normal[i]); 158 | if (v > max) 159 | { 160 | x = i; 161 | max = v; 162 | } 163 | } 164 | if (x==-1) 165 | Error ("BaseWindingForPlane: no axis found"); 166 | 167 | VectorCopy (vec3_origin, vup); 168 | switch (x) 169 | { 170 | case 0: 171 | case 1: 172 | vup[2] = 1; 173 | break; 174 | case 2: 175 | vup[0] = 1; 176 | break; 177 | } 178 | 179 | v = DotProduct (vup, normal); 180 | VectorMA (vup, -v, normal, vup); 181 | VectorNormalize (vup); 182 | 183 | VectorScale (normal, dist, org); 184 | 185 | CrossProduct (vup, normal, vright); 186 | 187 | VectorScale (vup, 8192, vup); 188 | VectorScale (vright, 8192, vright); 189 | 190 | // project a really big axis aligned box onto the plane 191 | w = AllocWinding (4); 192 | 193 | VectorSubtract (org, vright, w->p[0]); 194 | VectorAdd (w->p[0], vup, w->p[0]); 195 | 196 | VectorAdd (org, vright, w->p[1]); 197 | VectorAdd (w->p[1], vup, w->p[1]); 198 | 199 | VectorAdd (org, vright, w->p[2]); 200 | VectorSubtract (w->p[2], vup, w->p[2]); 201 | 202 | VectorSubtract (org, vright, w->p[3]); 203 | VectorSubtract (w->p[3], vup, w->p[3]); 204 | 205 | w->numpoints = 4; 206 | 207 | return w; 208 | } 209 | 210 | /* 211 | ================== 212 | CopyWinding 213 | ================== 214 | */ 215 | winding_t *CopyWinding (winding_t *w) 216 | { 217 | int size; 218 | winding_t *c; 219 | 220 | size = (int)((winding_t *)0)->p[w->numpoints]; 221 | c = malloc (size); 222 | memcpy (c, w, size); 223 | return c; 224 | } 225 | 226 | 227 | /* 228 | ============= 229 | ClipWinding 230 | ============= 231 | */ 232 | void ClipWinding (winding_t *in, vec3_t normal, vec_t dist, 233 | winding_t **front, winding_t **back) 234 | { 235 | vec_t dists[MAX_POINTS_ON_WINDING+4]; 236 | int sides[MAX_POINTS_ON_WINDING+4]; 237 | int counts[3]; 238 | vec_t dot; 239 | int i, j; 240 | vec_t *p1, *p2; 241 | vec3_t mid; 242 | winding_t *f, *b; 243 | int maxpts; 244 | 245 | counts[0] = counts[1] = counts[2] = 0; 246 | 247 | // determine sides for each point 248 | for (i=0 ; inumpoints ; i++) 249 | { 250 | dot = DotProduct (in->p[i], normal); 251 | dot -= dist; 252 | dists[i] = dot; 253 | if (dot > ON_EPSILON) 254 | sides[i] = SIDE_FRONT; 255 | else if (dot < -ON_EPSILON) 256 | sides[i] = SIDE_BACK; 257 | else 258 | { 259 | sides[i] = SIDE_ON; 260 | } 261 | counts[sides[i]]++; 262 | } 263 | sides[i] = sides[0]; 264 | dists[i] = dists[0]; 265 | 266 | *front = *back = NULL; 267 | 268 | if (!counts[0]) 269 | { 270 | *back = CopyWinding (in); 271 | return; 272 | } 273 | if (!counts[1]) 274 | { 275 | *front = CopyWinding (in); 276 | return; 277 | } 278 | 279 | maxpts = in->numpoints+4; // can't use counts[0]+2 because 280 | // of fp grouping errors 281 | 282 | *front = f = AllocWinding (maxpts); 283 | *back = b = AllocWinding (maxpts); 284 | 285 | for (i=0 ; inumpoints ; i++) 286 | { 287 | p1 = in->p[i]; 288 | 289 | if (sides[i] == SIDE_ON) 290 | { 291 | VectorCopy (p1, f->p[f->numpoints]); 292 | f->numpoints++; 293 | VectorCopy (p1, b->p[b->numpoints]); 294 | b->numpoints++; 295 | continue; 296 | } 297 | 298 | if (sides[i] == SIDE_FRONT) 299 | { 300 | VectorCopy (p1, f->p[f->numpoints]); 301 | f->numpoints++; 302 | } 303 | if (sides[i] == SIDE_BACK) 304 | { 305 | VectorCopy (p1, b->p[b->numpoints]); 306 | b->numpoints++; 307 | } 308 | 309 | if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) 310 | continue; 311 | 312 | // generate a split point 313 | p2 = in->p[(i+1)%in->numpoints]; 314 | 315 | dot = dists[i] / (dists[i]-dists[i+1]); 316 | for (j=0 ; j<3 ; j++) 317 | { // avoid round off error when possible 318 | if (normal[j] == 1) 319 | mid[j] = dist; 320 | else if (normal[j] == -1) 321 | mid[j] = -dist; 322 | else 323 | mid[j] = p1[j] + dot*(p2[j]-p1[j]); 324 | } 325 | 326 | VectorCopy (mid, f->p[f->numpoints]); 327 | f->numpoints++; 328 | VectorCopy (mid, b->p[b->numpoints]); 329 | b->numpoints++; 330 | } 331 | 332 | if (f->numpoints > maxpts || b->numpoints > maxpts) 333 | Error ("ClipWinding: points exceeded estimate"); 334 | if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) 335 | Error ("ClipWinding: MAX_POINTS_ON_WINDING"); 336 | } 337 | 338 | /* 339 | ================= 340 | ChopWinding 341 | 342 | Returns the fragment of in that is on the front side 343 | of the cliping plane. The original is freed. 344 | ================= 345 | */ 346 | winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist) 347 | { 348 | winding_t *f, *b; 349 | 350 | ClipWinding (in, normal, dist, &f, &b); 351 | free (in); 352 | if (b) 353 | free (b); 354 | return f; 355 | } 356 | 357 | /* 358 | ================= 359 | CheckWinding 360 | 361 | ================= 362 | */ 363 | void CheckWinding (winding_t *w) 364 | { 365 | int i, j; 366 | vec_t *p1, *p2; 367 | vec_t d, edgedist; 368 | vec3_t dir, edgenormal, facenormal; 369 | vec_t area; 370 | vec_t facedist; 371 | 372 | if (w->numpoints < 3) 373 | Error ("CheckFace: %i points",w->numpoints); 374 | 375 | area = WindingArea(w); 376 | if (area < 1) 377 | Error ("CheckFace: %f area", area); 378 | 379 | WindingPlane (w, facenormal, &facedist); 380 | 381 | for (i=0 ; inumpoints ; i++) 382 | { 383 | p1 = w->p[i]; 384 | 385 | for (j=0 ; j<3 ; j++) 386 | if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE) 387 | Error ("CheckFace: BUGUS_RANGE: %f",p1[j]); 388 | 389 | j = i+1 == w->numpoints ? 0 : i+1; 390 | 391 | // check the point is on the face plane 392 | d = DotProduct (p1, facenormal) - facedist; 393 | if (d < -ON_EPSILON || d > ON_EPSILON) 394 | Error ("CheckFace: point off plane"); 395 | 396 | // check the edge isn't degenerate 397 | p2 = w->p[j]; 398 | VectorSubtract (p2, p1, dir); 399 | 400 | if (VectorLength (dir) < ON_EPSILON) 401 | Error ("CheckFace: degenerate edge"); 402 | 403 | CrossProduct (facenormal, dir, edgenormal); 404 | VectorNormalize (edgenormal); 405 | edgedist = DotProduct (p1, edgenormal); 406 | edgedist += ON_EPSILON; 407 | 408 | // all other points must be on front side 409 | for (j=0 ; jnumpoints ; j++) 410 | { 411 | if (j == i) 412 | continue; 413 | d = DotProduct (w->p[j], edgenormal); 414 | if (d > edgedist) 415 | Error ("CheckFace: non-convex"); 416 | } 417 | } 418 | } 419 | 420 | -------------------------------------------------------------------------------- /qc/plats.qc: -------------------------------------------------------------------------------- 1 | /* 2 | plats.qc 3 | 4 | platform functions 5 | 6 | Copyright (C) 1996-1997 Id Software, Inc. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 | 17 | See the GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to: 21 | 22 | Free Software Foundation, Inc. 23 | 59 Temple Place - Suite 330 24 | Boston, MA 02111-1307, USA 25 | 26 | */ 27 | 28 | 29 | void() plat_center_touch; 30 | void() plat_outside_touch; 31 | void() plat_trigger_use; 32 | void() plat_go_up; 33 | void() plat_go_down; 34 | void() plat_crush; 35 | float PLAT_LOW_TRIGGER = 1; 36 | 37 | void() plat_spawn_inside_trigger = 38 | { 39 | local entity trigger; 40 | local vector tmin, tmax; 41 | 42 | // 43 | // middle trigger 44 | // 45 | trigger = spawn(); 46 | trigger.touch = plat_center_touch; 47 | trigger.movetype = MOVETYPE_NONE; 48 | trigger.solid = SOLID_TRIGGER; 49 | trigger.enemy = self; 50 | 51 | tmin = self.mins + '25 25 0'; 52 | tmax = self.maxs - '25 25 -8'; 53 | tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8); 54 | if (self.spawnflags & PLAT_LOW_TRIGGER) 55 | tmax_z = tmin_z + 8; 56 | 57 | if (self.size_x <= 50) 58 | { 59 | tmin_x = (self.mins_x + self.maxs_x) / 2; 60 | tmax_x = tmin_x + 1; 61 | } 62 | if (self.size_y <= 50) 63 | { 64 | tmin_y = (self.mins_y + self.maxs_y) / 2; 65 | tmax_y = tmin_y + 1; 66 | } 67 | 68 | setsize (trigger, tmin, tmax); 69 | }; 70 | 71 | void() plat_hit_top = 72 | { 73 | sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise1, 1, ATTN_NORM); 74 | self.state = STATE_TOP; 75 | self.think = plat_go_down; 76 | self.nextthink = self.ltime + 3; 77 | }; 78 | 79 | void() plat_hit_bottom = 80 | { 81 | sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise1, 1, ATTN_NORM); 82 | self.state = STATE_BOTTOM; 83 | }; 84 | 85 | void() plat_go_down = 86 | { 87 | sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM); 88 | self.state = STATE_DOWN; 89 | SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom); 90 | }; 91 | 92 | void() plat_go_up = 93 | { 94 | sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM); 95 | self.state = STATE_UP; 96 | SUB_CalcMove (self.pos1, self.speed, plat_hit_top); 97 | }; 98 | 99 | void() plat_center_touch = 100 | { 101 | if (other.classname != "player") 102 | return; 103 | 104 | if (other.health <= 0) 105 | return; 106 | 107 | self = self.enemy; 108 | if (self.state == STATE_BOTTOM) 109 | plat_go_up (); 110 | else if (self.state == STATE_TOP) 111 | self.nextthink = self.ltime + 1; // delay going down 112 | }; 113 | 114 | void() plat_outside_touch = 115 | { 116 | if (other.classname != "player") 117 | return; 118 | 119 | if (other.health <= 0) 120 | return; 121 | 122 | //dprint ("plat_outside_touch\n"); 123 | self = self.enemy; 124 | if (self.state == STATE_TOP) 125 | plat_go_down (); 126 | }; 127 | 128 | void() plat_trigger_use = 129 | { 130 | if (self.think) 131 | return; // allready activated 132 | plat_go_down(); 133 | }; 134 | 135 | 136 | void() plat_crush = 137 | { 138 | //dprint ("plat_crush\n"); 139 | 140 | other.deathtype = "squish"; 141 | T_Damage (other, self, self, 1); 142 | 143 | if (self.state == STATE_UP) 144 | plat_go_down (); 145 | else if (self.state == STATE_DOWN) 146 | plat_go_up (); 147 | else 148 | objerror ("plat_crush: bad self.state\n"); 149 | }; 150 | 151 | void() plat_use = 152 | { 153 | self.use = SUB_Null; 154 | if (self.state != STATE_UP) 155 | objerror ("plat_use: not in up state"); 156 | plat_go_down(); 157 | }; 158 | 159 | 160 | /*QUAKED func_plat (0 .5 .8) ? PLAT_LOW_TRIGGER 161 | speed default 150 162 | 163 | Plats are always drawn in the extended position, so they will light correctly. 164 | 165 | If the plat is the target of another trigger or button, it will start out disabled in the extended position until it is trigger, when it will lower and become a normal plat. 166 | 167 | If the "height" key is set, that will determine the amount the plat moves, instead of being implicitly determined by the model's height. 168 | Set "sounds" to one of the following: 169 | 1) base fast 170 | 2) chain slow 171 | */ 172 | 173 | 174 | void() func_plat = 175 | 176 | { 177 | local entity t; 178 | 179 | if (!self.t_length) 180 | self.t_length = 80; 181 | if (!self.t_width) 182 | self.t_width = 10; 183 | 184 | if (self.sounds == 0) 185 | self.sounds = 2; 186 | // FIX THIS TO LOAD A GENERIC PLAT SOUND 187 | 188 | if (self.sounds == 1) 189 | { 190 | precache_sound ("plats/plat1.wav"); 191 | precache_sound ("plats/plat2.wav"); 192 | self.noise = "plats/plat1.wav"; 193 | self.noise1 = "plats/plat2.wav"; 194 | } 195 | 196 | if (self.sounds == 2) 197 | { 198 | precache_sound ("plats/medplat1.wav"); 199 | precache_sound ("plats/medplat2.wav"); 200 | self.noise = "plats/medplat1.wav"; 201 | self.noise1 = "plats/medplat2.wav"; 202 | } 203 | 204 | 205 | self.mangle = self.angles; 206 | self.angles = '0 0 0'; 207 | 208 | self.classname = "plat"; 209 | self.solid = SOLID_BSP; 210 | self.movetype = MOVETYPE_PUSH; 211 | setorigin (self, self.origin); 212 | setmodel (self, self.model); 213 | setsize (self, self.mins , self.maxs); 214 | 215 | self.blocked = plat_crush; 216 | if (!self.speed) 217 | self.speed = 150; 218 | 219 | // pos1 is the top position, pos2 is the bottom 220 | self.pos1 = self.origin; 221 | self.pos2 = self.origin; 222 | if (self.height) 223 | self.pos2_z = self.origin_z - self.height; 224 | else 225 | self.pos2_z = self.origin_z - self.size_z + 8; 226 | 227 | self.use = plat_trigger_use; 228 | 229 | plat_spawn_inside_trigger (); // the "start moving" trigger 230 | 231 | if (self.targetname) 232 | { 233 | self.state = STATE_UP; 234 | self.use = plat_use; 235 | } 236 | else 237 | { 238 | setorigin (self, self.pos2); 239 | self.state = STATE_BOTTOM; 240 | } 241 | }; 242 | 243 | //============================================================================ 244 | 245 | void() train_next; 246 | void() func_train_find; 247 | 248 | void() train_blocked = 249 | { 250 | if (time < self.attack_finished) 251 | return; 252 | self.attack_finished = time + 0.5; 253 | other.deathtype = "squish"; 254 | T_Damage (other, self, self, self.dmg); 255 | }; 256 | 257 | void() train_use = 258 | { 259 | if (self.think != func_train_find) 260 | return; // already activated 261 | train_next(); 262 | }; 263 | 264 | void() train_wait = 265 | { 266 | if (self.wait) 267 | { 268 | self.nextthink = self.ltime + self.wait; 269 | sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise, 1, ATTN_NORM); 270 | } 271 | else 272 | self.nextthink = self.ltime + 0.1; 273 | 274 | self.think = train_next; 275 | }; 276 | 277 | void() train_next = 278 | { 279 | local entity targ; 280 | 281 | targ = find (world, targetname, self.target); 282 | self.target = targ.target; 283 | if (!self.target) 284 | objerror ("train_next: no next target"); 285 | if (targ.wait) 286 | self.wait = targ.wait; 287 | else 288 | self.wait = 0; 289 | sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM); 290 | SUB_CalcMove (targ.origin - self.mins, self.speed, train_wait); 291 | }; 292 | 293 | void() func_train_find = 294 | 295 | { 296 | local entity targ; 297 | 298 | targ = find (world, targetname, self.target); 299 | self.target = targ.target; 300 | setorigin (self, targ.origin - self.mins); 301 | if (!self.targetname) 302 | { // not triggered, so start immediately 303 | self.nextthink = self.ltime + 0.1; 304 | self.think = train_next; 305 | } 306 | }; 307 | 308 | /*QUAKED func_train (0 .5 .8) ? 309 | Trains are moving platforms that players can ride. 310 | The targets origin specifies the min point of the train at each corner. 311 | The train spawns at the first target it is pointing at. 312 | If the train is the target of a button or trigger, it will not begin moving until activated. 313 | speed default 100 314 | dmg default 2 315 | sounds 316 | 1) ratchet metal 317 | 318 | */ 319 | void() func_train = 320 | { 321 | if (!self.speed) 322 | self.speed = 100; 323 | if (!self.target) 324 | objerror ("func_train without a target"); 325 | if (!self.dmg) 326 | self.dmg = 2; 327 | 328 | if (self.sounds == 0) 329 | { 330 | self.noise = ("misc/null.wav"); 331 | precache_sound ("misc/null.wav"); 332 | self.noise1 = ("misc/null.wav"); 333 | precache_sound ("misc/null.wav"); 334 | } 335 | 336 | if (self.sounds == 1) 337 | { 338 | self.noise = ("plats/train2.wav"); 339 | precache_sound ("plats/train2.wav"); 340 | self.noise1 = ("plats/train1.wav"); 341 | precache_sound ("plats/train1.wav"); 342 | } 343 | 344 | self.cnt = 1; 345 | self.solid = SOLID_BSP; 346 | self.movetype = MOVETYPE_PUSH; 347 | self.blocked = train_blocked; 348 | self.use = train_use; 349 | self.classname = "train"; 350 | 351 | setmodel (self, self.model); 352 | setsize (self, self.mins , self.maxs); 353 | setorigin (self, self.origin); 354 | 355 | // start trains on the second frame, to make sure their targets have had 356 | // a chance to spawn 357 | self.nextthink = self.ltime + 0.1; 358 | self.think = func_train_find; 359 | }; 360 | 361 | /*QUAKED misc_teleporttrain (0 .5 .8) (-8 -8 -8) (8 8 8) 362 | This is used for the final bos 363 | */ 364 | void() misc_teleporttrain = 365 | { 366 | if (!self.speed) 367 | self.speed = 100; 368 | if (!self.target) 369 | objerror ("func_train without a target"); 370 | 371 | self.cnt = 1; 372 | self.solid = SOLID_NOT; 373 | self.movetype = MOVETYPE_PUSH; 374 | self.blocked = train_blocked; 375 | self.use = train_use; 376 | self.avelocity = '100 200 300'; 377 | 378 | self.noise = ("misc/null.wav"); 379 | precache_sound ("misc/null.wav"); 380 | self.noise1 = ("misc/null.wav"); 381 | precache_sound ("misc/null.wav"); 382 | 383 | precache_model2 ("progs/teleport.mdl"); 384 | setmodel (self, "progs/teleport.mdl"); 385 | setsize (self, self.mins , self.maxs); 386 | setorigin (self, self.origin); 387 | 388 | // start trains on the second frame, to make sure their targets have had 389 | // a chance to spawn 390 | self.nextthink = self.ltime + 0.1; 391 | self.think = func_train_find; 392 | }; 393 | 394 | --------------------------------------------------------------------------------