as released 2002-05-24

This commit is contained in:
archive 2002-05-24 00:00:00 +00:00
commit 930d214707
270 changed files with 117620 additions and 0 deletions

BIN
MP_sdk_header4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

169
UK-PC-EULA Level Editor.rtf Normal file
View File

@ -0,0 +1,169 @@
{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial{\*\falt Helvetica};}
{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f86\fnil\fcharset77\fprq0{\*\panose 00000000000000000000}Font8721{\*\falt Times New Roman};}{\f87\froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}
{\f88\froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}{\f90\froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\f91\froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
{\f92\froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\f93\froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}{\f94\froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}
{\f95\fswiss\fcharset238\fprq2 Arial CE{\*\falt Helvetica};}{\f96\fswiss\fcharset204\fprq2 Arial Cyr{\*\falt Helvetica};}{\f98\fswiss\fcharset161\fprq2 Arial Greek{\*\falt Helvetica};}{\f99\fswiss\fcharset162\fprq2 Arial Tur{\*\falt Helvetica};}
{\f100\fswiss\fcharset177\fprq2 Arial (Hebrew){\*\falt Helvetica};}{\f101\fswiss\fcharset178\fprq2 Arial (Arabic){\*\falt Helvetica};}{\f102\fswiss\fcharset186\fprq2 Arial Baltic{\*\falt Helvetica};}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;
\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;
\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal;}{\*\cs10 \additive
Default Paragraph Font;}{\s15\ql \li0\ri0\sb72\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f86\fs18\lang1024\langfe1024\cgrid\noproof\langnp1033\langfenp1033 \sbasedon0 \snext15 Body;}{
\s16\ql \fi-170\li170\ri0\sb72\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin170\itap0 \f86\fs18\lang1024\langfe1024\cgrid\noproof\langnp1033\langfenp1033 \sbasedon0 \snext16 Bullet;}{\s17\ql \fi-360\li360\ri0\widctlpar\jclisttab\tx360{\*\pn
\pnlvlbody\ilvl0\ls4\pnrnot0\pndec }\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin360\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext17 \sautoupd List Bullet;}{\s18\ql \li0\ri0\widctlpar\nooverflow\faauto\rin0\lin0\itap0
\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext18 Body Text;}}{\*\listtable{\list\listtemplateid-682570846\listsimple{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0
{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \s17\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid-119}{\list\listtemplateid0{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0
\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00);}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0
\levelindent0{\leveltext\'02\'01);}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li720\jclisttab\tx720 }{\listlevel\levelnfc2\levelnfcn2\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'02\'02);}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'03(\'03);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li1440\jclisttab\tx1440 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'03(\'04);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li1800\jclisttab\tx1800 }{\listlevel\levelnfc2\levelnfcn2\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'03(\'05);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li2160\jclisttab\tx2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'02\'06.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li2520\jclisttab\tx2520 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'02\'07.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li2880\jclisttab\tx2880 }{\listlevel\levelnfc2\levelnfcn2\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'02\'08.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li3240\jclisttab\tx3240 }{\listname ;}\listid1422678978}}{\*\listoverridetable{\listoverride\listid1422678978\listoverridecount9{\lfolevel\listoverrideformat
{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00);}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc4
\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'01);}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc2\levelnfcn2\leveljc0
\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'02);}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0
\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'03);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1
\levelspace0\levelindent0{\leveltext\'03(\'04);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc2\levelnfcn2\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0
{\leveltext\'03(\'05);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'02\'06.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'07.;}{\levelnumbers
\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc2\levelnfcn2\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'08.;}{\levelnumbers\'01;}\chbrdr
\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}\ls1}{\listoverride\listid1422678978\listoverridecount9{\lfolevel\listoverrideformat{\listlevel\levelnfc1\levelnfcn1\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc3\levelnfcn3\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'01.;}{\levelnumbers
\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'02.;}{\levelnumbers\'01;}\chbrdr
\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'03);}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1
\chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'04);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1
\chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'05);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1
\chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc2\levelnfcn2\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'06);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1
\chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'07);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1
\chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc2\levelnfcn2\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'08);}{\levelnumbers\'02;}\chbrdr\brdrnone\brdrcf1
\chshdng0\chcfpat1\chcbpat1 }}\ls2}{\listoverride\listid1422678978\listoverridecount9{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers
\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'04\'00.\'01.;}{\levelnumbers\'01\'03;}\chbrdr
\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'06\'00.\'01.\'02.;}{\levelnumbers\'01\'03\'05;}\chbrdr
\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'08\'00.\'01.\'02.\'03.;}{\levelnumbers\'01\'03\'05\'07;}
\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0a\'00.\'01.\'02.\'03.\'04.;}{\levelnumbers
\'01\'03\'05\'07\'09;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'0c\'00.\'01.\'02.\'03.\'04.\'05.;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0
\levelindent0{\leveltext\'0e\'00.\'01.\'02.\'03.\'04.\'05.\'06.;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0
\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'10\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }}{\lfolevel\listoverrideformat{\listlevel
\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'12\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08.;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\chbrdr\brdrnone\brdrcf1
\chshdng0\chcfpat1\chcbpat1 }}\ls3}{\listoverride\listid-119\listoverridecount0\ls4}}{\info{\title SOFTWARE LICENSE AGREEMENT}{\author Mike Rivera}{\operator Rick Johnson}{\creatim\yr2002\mo5\dy9\hr15\min1}{\revtim\yr2002\mo5\dy9\hr15\min1}{\version2}
{\edmins0}{\nofpages3}{\nofwords1802}{\nofchars10272}{\nofcharsws12614}{\vern8247}}\margl2160\margr2160 \widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin2160
\dgvorigin1440\dghshow1\dgvshow1\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule \fet0\sectd \linex0\endnhere\sectdefaultcl {\*\pnseclvl1
\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5
\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang
{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \s15\ql \li0\ri0\sb72\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0
\f86\fs18\lang1024\langfe1024\cgrid\noproof\langnp1033\langfenp1033 {\f1\fs20 SOFTWARE LICENSE AGREEMENT
\par }\pard \s15\ql \li0\ri0\sb7\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\f1\fs20
IMPORTANT - READ CAREFULLY: USE OF THIS PROGRAM IS SUBJECT TO THE SOFTWARE LICENSE TERMS SET FORTH BELOW. "PROGRAM" INCLUDES ALL SOFTWARE INCLUDED WITH THIS AGREEMENT, THE ASSOCIATED MEDIA, ANY PRINTED MATERIALS, AND ANY ONLINE O
R ELECTRONIC DOCUMENTATION, AND ANY AND ALL COPIES OF SUCH SOFTWARE AND MATERIALS. BY OPENING THIS PACKAGE, INSTALLING, AND/OR USING THE PROGRAM AND ANY SOFTWARE PROGRAMS INCLUDED WITHIN, YOU ACCEPT THE TERMS OF THIS LICENSE WITH ACTIVISION, INC. ("ACTIVI
SION").
\par LIMITED USE LICENSE. Subject to the conditions described below, Activision grants you the non-exclusive, non-transferable, limited right and license to install and use one copy of this Program solely and exclusively for your personal use. All right
s not specifically granted under this Agreement are reserved by Activision and, as applicable, Activision\rquote
s licensors. This Program is licensed, not sold, for your use. Your license confers no title or ownership in this Program and should not be construed as a sale of any rights in this Program.
\par
\par LICENSE CONDITIONS.
\par You shall not:
\par }\pard\plain \s16\ql \fi-170\li170\ri0\sb7\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin170\itap0 \f86\fs18\lang1024\langfe1024\cgrid\noproof\langnp1033\langfenp1033 {\f1\fs20 \bullet \tab }{\f1\fs20
Exploit this Program or any of its parts commercially, including but not limited to use at a cyber cafe, computer gaming center or any other location-based site. Activision may
offer a separate Site License Agreement to permit you to make this Program available for commercial use; see the contact information below.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 Use this Program, or permit use of this Program, on more than one computer, computer terminal, or workstation at the same time.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 Make copies of this Program or any part thereof, or make copies of the materials accompanying this Program.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 Copy this Program onto a hard drive or other storage device; you must run this Program from the included CD-ROM (although this Pr
ogram itself may automatically copy a portion of this Program onto your hard drive during installation in order to run more efficiently).
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 Use the program, or permit use of this Program, in a network, multi-user arrangement or remote access arrangement, including any online use, except as otherwise explicitly provided by this Program.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 Sell, rent, lease, license, distribute or otherwise transfer this Program, or any copies of this Program, without the express prior written consent of Activision.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 Reverse engineer, derive source code, modify, decompile, disassemble, or create derivative works of this Program, in whole or in part.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 Remove, disable or circumvent any proprietary notices or labels contained on or within the Program.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 Export or re-export this Program or any copy or adaptation in violation of any applicable laws or regulations of the United Sates government.
\par
\par }\pard\plain \s15\ql \li0\ri0\sb7\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f86\fs18\lang1024\langfe1024\cgrid\noproof\langnp1033\langfenp1033 {\f1\fs20
OWNERSHIP. All title, ownership rights and intellectual property rights in and to this Program and any and all copies thereof (including
but not limited to any titles, computer code, themes, objects, characters, character names, stories, dialog, catch phrases, locations, concepts, artwork, animation, sounds, musical compositions, audio-visual effects, methods of operation, moral rights, a
ny related documentation, and "applets" incorporated into this Program) are owned by Activision, affiliates of Activision or Activision\rquote
s licensors. This Program is protected by the copyright laws of the United States, international copyright treaties and conventions and other laws. This Program contains certain licensed materials and Activision\rquote
s licensors may protect their rights in the event of any violation of this Agreement.
\par PROGRAM UTILITIES. This Program contains certain design, programming and proces
sing utilities, tools, assets and other resources ("Program Utilities") for use with this Program that allow you to create customized new game levels and other related game materials for personal use in connection with the Program ("New Game Materials").
The use of the Program Utilities is subject to the following additional license restrictions:
\par }\pard\plain \s16\ql \fi-170\li170\ri0\sb7\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin170\itap0 \f86\fs18\lang1024\langfe1024\cgrid\noproof\langnp1033\langfenp1033 {\f1\fs20 \bullet \tab }{\f1\fs20
You agree that, as a condition to your using the Program Utilities, you will not use or allow third parties to use the Program Utilities and the New Game Materia
ls created by you for any commercial purposes, including but not limited to selling, renting, leasing, licensing, distributing, or otherwise transferring the ownership of such New Game Materials, whether on a stand alone basis or packaged in combination w
i
th the New Game Materials created by others, through any and all distribution channels, including, without limitation, retail sales and on-line electronic distribution. You agree not to solicit, initiate or encourage any proposal or offer from any person
or entity to create any New Game Materials for commercial distribution. You agree to promptly inform Activision in writing of any instances of your receipt of any such proposal or offer.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 If you decide to make available the use of the New Game Materials created by you to other gamers, you agree to do so solely without charge.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 New Game Materials shall not contain modifications to any COM, EXE or DLL files or to any other executable Product files.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 New Game Materials may be created only if such New Game Materials can be used exclusively in combination with the retail version of the Program. New Game Materials may not be designed to be used as a stand-alone product.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 New Game Materials must not contain any illegal, obscene or defamatory materials, material
s that infringe rights of privacy and publicity of third parties or (without appropriate irrevocable licenses granted specifically for that purpose) any trademarks, copyright-protected works or other properties of third parties.
\par }{\f1\fs20 \bullet \tab }{\f1\fs20 All New Game Materials must contain prominent identification at least in any on-line description and with reasonable duration on the opening screen: (a) the name and E-mail address of the New Game Materials\rquote
creator(s) and (b) the words "THIS MATERIAL IS NOT MADE OR SUPPORTED BY ACTIVISION."
\par
\par }\pard\plain \s15\ql \li0\ri0\sb7\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f86\fs18\lang1024\langfe1024\cgrid\noproof\langnp1033\langfenp1033 {\f1\fs20
LIMITED WARRANTY: Activision warrants to the original consumer purchaser of this Program that the recording medium on which the Program is recorded will be free from defects in material and workmanship for 90 days from the date of purchase. If
the recording medium is found defective within 90 days of original purchase, Activision agrees to replace, free of charge, any product discovered to be defective within such period upon its receipt of the Product, postage paid, with proof of the date of
p
urchase, as long as the Program is still being manufactured by Activision. In the event that the Program is no longer available, Activision retains the right to substitute a similar program of equal or greater value. This warranty is limited to the record
i
ng medium containing the Program as originally provided by Activision and is not applicable to normal wear and tear. This warranty shall not be applicable and shall be void if the defect has arisen through abuse, mistreatment, or neglect. Any implied warr
anties prescribed by statute are expressly limited to the 90-day period described above.
\par }\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20
EXCEPT AS SET FORTH ABOVE, THIS WARRANTY IS IN LIEU OF ALL OTHER WARRANTIES, WHETHER ORAL OR WRITTEN, EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, FIT
NESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, AND NO OTHER REPRESENTATIONS OR CLAIMS OF ANY KIND SHALL BE BINDING ON OR OBLIGATE ACTIVISION. }{\f1\fs20
WILL ACTIVISION BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGE RESULTING FROM POSSESSION, USE OR M
ALFUNCTION OF THIS PRODUCT, INCLUDING DAMAGE TO PROPERTY AND, TO THE EXTENT PERMITTED BY LAW, DAMAGES FOR PERSONAL INJURY, EVEN IF ACTIVISION HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED
W
ARRANTY LASTS AND/OR THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATIONS AND/OR EXCLUSION OR LIMITATION OF LIABILITY MAY NOT APPLY TO YOU. THIS WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS, AND YOU MAY HAVE OTHER RIGHT
S WHICH VARY FROM STATE TO STATE.
\par }\pard\plain \s15\ql \li0\ri0\sb7\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f86\fs18\lang1024\langfe1024\cgrid\noproof\langnp1033\langfenp1033 {\f1\fs20
When returning the Program for warranty replacement please send the original product disks only in protective packaging and include: (1) a photocopy of your dated sales receipt; (2) your name and return address typed or cle
arly printed; (3) a brief note describing the defect, the problem(s) you are encountered and the system on which you are running the Program; (4) if you are returning the Program after the 90-day warranty period, but within one year after the date of purc
hase, please include cheque or money order payable to Activision for $10\~U.S. ($19 AUD for Australia, or }{\f1\fs20 \'a310.00}{\f1\fs20 for Europe) currency per CD. Note: Certified mail recommended.
\par }\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 In Europe send to:
\par
\par }\pard \ql \li0\ri0\widctlpar\nooverflow\faauto\rin0\lin0\itap0 {\f1\fs20 WARRANTY REPLACEMENTS}{\f1\fs20\lang2057\langfe1033\langnp2057
\par }\pard\plain \s18\ql \li0\ri0\widctlpar\nooverflow\faauto\rin0\lin0\itap0 \fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f1\fs20\lang1033\langfe1033\langnp1033 ACTIVISION (UK) Ltd., Parliament House,
St Laurence Way, Slough, Berkshire, SL1 2BW, United Kingdom.
\par }\pard\plain \ql \li0\ri0\widctlpar\nooverflow\faauto\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 Disc Replacement: +44 (0)}{\f1\fs20\cf6 }{\f1\fs20 8705 143 525}{\f1\fs20\lang2057\langfe1033\langnp2057
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\f1\fs20
\par
\par In Australia send to:
\par
\par Warranty Replacements
\par Activision
\par }\pard \ql \li0\ri0\widctlpar\nooverflow\faauto\rin0\lin0\itap0 {\f1\fs20 Century Plaza}{\f1\fs20
\par }{\f1\fs20 41 Rawson Street}{\f1\fs20
\par }{\f1\fs20 Epping, NSW 2121}{\f1\fs20
\par }{\f1\fs20 Australia}{\f1\fs20
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\f1\fs20
\par }\pard\plain \s15\ql \li0\ri0\sb7\keep\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f86\fs18\lang1024\langfe1024\cgrid\noproof\langnp1033\langfenp1033 {\f1\fs20 LIMITATION ON DAMAGES: IN NO EVENT WILL
ACTIVISION BE LIABLE FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES RESULTING FROM POSSESSION, USE OR MALFUNCTION OF THE PROGRAM, INCLUDING DAMAGES TO PROPERTY, LOSS OF GOODWILL, COMPUTER FAILURE OR MALFUNCTION AND, TO THE EXTENT PERMITTED BY LAW, DAMA
GES FOR PERSONAL INJURIES, EVEN IF ACTIVISION HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ACTIVISION\rquote
S LIABILITY SHALL NOT EXCEED THE ACTUAL PRICE PAID FOR THE LICENSE TO USE THIS PROGRAM. SOME STATES/COUNTRIES DO NOT ALLOW LIMITATIONS ON HOW LONG
AN IMPLIED WARRANTY LASTS AND/OR THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATIONS AND/OR EXCLUSION OR LIMITATION OF LIABILITY MAY NOT APPLY TO YOU. THIS WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS, AND YOU MAY HAVE
OTHER RIGHTS WHICH VARY FROM JURISDICTION TO JURISDICTION.
\par
\par TERMINATION: Without prejudice to any other rights of Activision, this Agreement will terminate automatically if you fail to comply with its terms and conditions. In such event, you must destroy all copies of this Program and all of its component parts.
\par U.S. GOVERNMENT RESTRICTED RIGHTS: The Program and documentation have been developed entirely at private expense and are provided as "Commercial Computer Software" or "restricted computer software."
Use, duplication or disclosure by the U.S. Government or a U.S. Government subcontractor is subject to the restrictions set forth in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software clauses in DFARS 252.227-7013 or as set for
th in subparagraph (c)(1) and (2) of the Commercial Computer Software Restricted Rights clauses at FAR 52.227-19, as applicable. The Contractor/Manufacturer is Activision, Inc., 3100 Ocean Park Boulevard, Santa Monica, California 90405.
\par INJUNCTION: Because
Activision would be irreparably damaged if the terms of this Agreement were not specifically enforced, you agree that Activision shall be entitled, without bond, other security or proof of damages, to appropriate equitable remedies with respect to breache
s of this Agreement, in addition to such other remedies as Activision may otherwise have under applicable laws.
\par
\par INDEMNITY: You agree to indemnify, defend and hold Activision, its partners, affiliates, licensors, contractors, officers, directors, employees
and agents harmless from all damages, losses and expenses arising directly or indirectly from your acts and omissions to act in using the Product pursuant to the terms of this Agreement.
\par
\par MISCELLANEOUS: This Agreement represents the complete agreement conc
erning this license between the parties and supersedes all prior agreements and representations between them. It may be amended only by a writing executed by both parties. If any provision of this Agreement is held to be unenforceable for any reason, such
provision shall be reformed only to the extent necessary to make it enforceable and the remaining provisions of this Agreement shall not be affected. This Agreement shall be construed under California law as such law is applied to agreements between Calif
ornia residents entered into and to be performed within California, except as governed by federal law and you consent to the exclusive jurisdiction of the state and federal courts in Los Angeles, California.
\par
\par If you have any questions concerning this license, you may contact Activision at 3100 Ocean Park Boulevard, Santa Monica, California 90405,}{\f1\fs20 USA,}{\f1\fs20 (310) 255-2000, Attn. Business and Legal Affairs, legal@activision.com}{\f1\fs20 .}{
\f1\fs20
\par }\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20
\par }}

140
US-PC-EULA Level-Editor.rtf Normal file
View File

@ -0,0 +1,140 @@
{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial{\*\falt Helvetica};}
{\f12\froman\fcharset0\fprq2{\*\panose 00000000000000000000}New York{\*\falt Times New Roman};}{\f27\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}{\f38\fswiss\fcharset0\fprq2{\*\panose 020b0603020202020204}Trebuchet MS;}
{\f85\fnil\fcharset77\fprq0{\*\panose 00000000000000000000}Font14579{\*\falt Times New Roman};}{\f86\froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\f87\froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
{\f89\froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\f90\froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}{\f91\froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}
{\f92\froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}{\f93\froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\f94\fswiss\fcharset238\fprq2 Arial CE{\*\falt Helvetica};}
{\f95\fswiss\fcharset204\fprq2 Arial Cyr{\*\falt Helvetica};}{\f97\fswiss\fcharset161\fprq2 Arial Greek{\*\falt Helvetica};}{\f98\fswiss\fcharset162\fprq2 Arial Tur{\*\falt Helvetica};}{\f99\fswiss\fcharset177\fprq2 Arial (Hebrew){\*\falt Helvetica};}
{\f100\fswiss\fcharset178\fprq2 Arial (Arabic){\*\falt Helvetica};}{\f101\fswiss\fcharset186\fprq2 Arial Baltic{\*\falt Helvetica};}{\f302\fswiss\fcharset238\fprq2 Tahoma CE;}{\f303\fswiss\fcharset204\fprq2 Tahoma Cyr;}
{\f305\fswiss\fcharset161\fprq2 Tahoma Greek;}{\f306\fswiss\fcharset162\fprq2 Tahoma Tur;}{\f307\fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f308\fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f309\fswiss\fcharset186\fprq2 Tahoma Baltic;}
{\f390\fswiss\fcharset238\fprq2 Trebuchet MS CE;}{\f394\fswiss\fcharset162\fprq2 Trebuchet MS Tur;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;
\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{
\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f27\fs24\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal;}{\s1\ql \li0\ri0\sb240\sa60\keepn\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0
\f38\fs48\lang1033\langfe1033\kerning32\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 heading 1;}{\s2\ql \li0\ri0\sb240\sa60\keepn\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f38\fs36\lang1033\langfe1033\cgrid\langnp1033\langfenp1033
\sbasedon0 \snext0 heading 2;}{\s3\ql \li0\ri0\sb240\sa60\keepn\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f38\fs28\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 heading 3;}{
\s4\ql \li0\ri0\sb240\sa60\keepn\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f38\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 heading 4;}{
\s5\ql \li0\ri0\sb240\sa60\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f38\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 heading 5;}{
\s6\ql \li0\ri0\sb240\sa60\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f38\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 heading 6;}{\*\cs10 \additive Default Paragraph Font;}{\*\cs15 \additive \ul\cf0
\sbasedon10 Hyperlink;}{\*\cs16 \additive \ul\cf0 \sbasedon10 FollowedHyperlink;}{\s17\ql \li0\ri0\sb60\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f12\fs18\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext17 Body;}
{\s18\ql \li0\ri0\sl480\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \caps\f85\fs54\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext18 Heading;}{
\s19\ql \fi-145\li288\ri0\sb60\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin288\itap0 \f12\fs18\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 Bullet;}{\s20\ql \li0\ri0\widctlpar\nooverflow\faauto\rin0\lin0\itap0
\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext20 Body Text;}}{\info{\title SOFTWARE LICENSE AGREEMENT}{\author Belinda M. Van Sickle}{\operator Rick Johnson}{\creatim\yr2002\mo5\dy9\hr14\min50}{\revtim\yr2002\mo5\dy9\hr14\min50}
{\printim\yr1999\mo8\dy13\hr8\min44}{\version2}{\edmins0}{\nofpages1}{\nofwords1706}{\nofchars9725}{\*\company Ignited Minds, LLC}{\nofcharsws11942}{\vern8247}}{\*\userprops {\propname Microsoft Theme}\proptype30{\staticval klingon-industrial 111}}
\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dghspace180\dgvspace180\dghorigin1701\dgvorigin1984\dghshow0\dgvshow0\jexpand\viewkind4\viewscale100\pgbrdrhead\pgbrdrfoot\htmautsp\nolnhtadjtbl\lnbrkrule
\fet0{\*\background {\shp{\*\shpinst\shpleft0\shptop0\shpright0\shpbottom0\shpfhdr0\shpbxmargin\shpbxignore\shpbymargin\shpbyignore\shpwr0\shpwrk0\shpfblwtxt1\shpz0\shplid1025{\sp{\sn shapeType}{\sv 1}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}
{\sp{\sn fillType}{\sv 3}}{\sp{\sn fillBlipName}{\sv indtextb}}{\sp{\sn fFilled}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn bWMode}{\sv 9}}{\sp{\sn fBackground}{\sv 1}}{\sp{\sn fLayoutInCell}{\sv 1}}}}}\sectd
\linex0\endnhere\pgbrdropt32\sectlinegrid360\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4
\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}
{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \s18\ql \li0\ri0\sl-480\slmult0
\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \caps\f85\fs54\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\f1\fs20 SOFTWARE LICENSE AGREEMENT
\par }\pard\plain \s17\ql \li0\ri0\sb29\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f12\fs18\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 IMPORTANT - READ CAREFULLY: YOUR USE OF THIS SOFTWARE (THE \'93PROGRAM\'94
) IS SUBJECT TO THE SOFTWARE LICENSE TERMS SET FORTH BELOW. THE \'93PROGRAM\'94 INCLUDES ALL SOFTWARE INCLUDED WITH THIS AGREEMENT, THE ASSOCIATED MEDIA, ANY PRINTED M
ATERIALS, AND ANY ON-LINE OR ELECTRONIC DOCUMENTATION, AND ANY AND ALL COPIES OF SUCH SOFTWARE AND MATERIALS. BY OPENING THIS PACKAGE, INSTALLING, AND/OR USING THE PROGRAM AND ANY SOFTWARE PROGRAMS INCLUDED WITHIN THE PROGRAM, YOU ACCEPT THE TERMS OF THIS
LICENSE WITH ACTIVISION, INC. (\'93ACTIVISION\'94).
\par
\par LIMITED USE LICENSE: Subject to the conditions described below, Activision grants you the non-exclusive, non-transferable, limited right and license to install and use one copy of the Program solely and exclu
sively for your personal use. All rights not specifically granted under this Agreement are reserved by Activision and, as applicable, Activision\rquote
s licensors. The Program is licensed, not sold, for your use. Your license confers no title or ownership in the
Program and should not be construed as a sale of any rights in the Program. All rights not specifically granted under this Agreement are reserved by Activision and, as applicable, its licensors.
\par
\par LICENSE CONDITIONS
\par You agree not to:
\par }\pard\plain \s19\ql \fi-113\li119\ri0\sb29\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin119\itap0 \f12\fs18\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \bullet \tab Exploit the Program
or any of its parts commercially, including but not limited to use at a cyber cafe, computer gaming center or any other location-based site. Activision may offer a separate Site License Agreement to permit you to make the Program available for commercial
use; see the contact information below.
\par \bullet \tab Sell, rent, lease, license, distribute or otherwise transfer this Program, or any copies of this Program, without the express prior written consent of Activision.
\par \bullet \tab Use the Program, or permit use of the Program, in a network, multi-user arrangement or remote access arrangement, including any on-line use, except as otherwise specifically provided by the Program.
\par \bullet \tab Use the Program, or permit use of the Program, on more than one computer, computer terminal, or workstation at the same time.
\par \bullet \tab Make copies of the Program or any part thereof, except for back up or archival purposes, or make copies of the materials accompanying the Program.
\par \bullet \tab Copy the Program onto a hard drive or other storage device; you must run the Program
from the included CD-ROM (although the Program itself may automatically copy a portion of the Program onto your hard drive during installation in order to run more efficiently).
\par \bullet \tab Reverse engineer, derive source code, modify, decompile, or disassemble the Program, in whole or in part.
\par \bullet \tab Remove, disable or circumvent any proprietary notices or labels contained on or within the Program.
\par \bullet \tab Export or re-export the Program or any copy or adaptation thereof in violation of any applicable laws or regulations.
\par }\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f27\fs24\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {
\par }\pard\plain \s17\ql \li0\ri0\sb29\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f12\fs18\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 OW
NERSHIP: All title, ownership rights and intellectual property rights in and to the Program and any and all copies thereof are owned by Activision or its licensors. The Program is protected by the copyright laws of the United States, international copyrig
ht treaties and conventions and other laws. The Program contains certain licensed materials and Activision\rquote
s licensors may protect their rights in the event of any violation of this Agreement. You agree not to remove, disable or circumvent any proprietary notices or labels contained on or within the Program.
\par
\par THE PROGRAM UTILITIES: The Program contains certain design, programming and processing utilities, tools, assets and other resources (\'93the Program Utilities\'94) for use with the Program that allow you to c
reate customized new game levels and other related game materials for personal use in connection with the Program (\'93New Game Materials\'94). The use of the Program Utilities is subject to the following additional license restrictions:
\par }\pard\plain \s19\ql \fi-108\li119\ri0\sb29\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin119\itap0 \f12\fs18\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 \bullet \tab You agree that, as a c
ondition to your using the Program Utilities, you will not use or allow third parties to use the Program Utilities and the New Game Materials created by you for any commercial purposes, including but not limited to selling, renting, leasing, licensing, di
s
tributing, or otherwise transferring the ownership of such New Game Materials, whether on a stand alone basis or packaged in combination with the New Game Materials created by others, through any and all distribution channels, including, without limitatio
n
, retail sales and on-line electronic distribution. You agree not to solicit, initiate or encourage any proposal or offer from any person or entity to create any New Game Materials for commercial distribution. You agree to promptly inform Activision in wr
iting of any instances of your receipt of any such proposal or offer.
\par \bullet \tab If you decide to make available the use of the New Game Materials created by you to other gamers, you agree to do so solely without charge.
\par \bullet \tab New Game Materials shall not contain modifications to any COM, EXE or DLL files or to any other executable Product files.
\par \bullet \tab New Game Materials may be created only if such New Game Materials can be used exclusively in combination with the retail version of the Program. New Game Materials may not be designed to be used as a stand-alone product.
\par \bullet \tab New Game Materials must not contain any illegal, obscene or defamatory materials, materials that infringe rights of privacy and publicity of third parties or (without appropriate irrevocable licenses granted
specifically for that purpose) any trademarks, copyright-protected works or other properties of third parties.
\par \bullet \tab All New Game Materials must contain prominent identification at least in any on-line description and with reasonable duration on the opening screen: (a) the name and E-mail address of the New Game Materials\rquote
creator(s) and (b) the words \'93THIS MATERIAL IS NOT MADE OR SUPPORTED BY ACTIVISION.\'94
\par }\pard\plain \s17\ql \li0\ri0\sb29\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f12\fs18\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20
\par LIMITED WARRANTY: Activision warrants to the original consumer purchaser of the Program that the record
ing medium on which the Program is recorded will be free from defects in material and workmanship for 90 days from the date of purchase. If the recording medium is found defective within 90 days of original purchase, Activision agrees to replace, free of
c
harge, any product discovered to be defective within such period upon its receipt of the Product, postage paid, with proof of the date of purchase, as long as the Program is still being manufactured by Activision. In the event that the Program is no longe
r
available, Activision retains the right to substitute a similar program of equal or greater value. This warranty is limited to the recording medium containing the Program as originally provided by Activision and is not applicable to normal wear and tear.
This warranty shall not be applicable and shall be void if the defect has arisen through abuse, mistreatment, or neglect. Any implied warranties prescribed by statute are expressly limited to the 90-day period described above.}{\f1\fs20
\par }{\f1\fs20 EXCEPT AS SET FORTH ABOVE, TH
IS WARRANTY IS IN LIEU OF ALL OTHER WARRANTIES, WHETHER ORAL OR WRITTEN, EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, AND NO OTHER REPRESENTATIONS OR CLAIMS OF ANY KIND SHALL BE BINDI
NG ON OR OBLIGATE ACTIVISION.
\par When returning the Program for warranty replacement please send the original product disks only in protective packaging and include: (1) a photocopy of your dated sales receipt; (2) your name and return address typed or clearl
y printed; (3) a brief note describing the defect, the problem(s) you are encountered and the system on which you are running the Program; (4) if you are returning the Program after the 90-day warranty period, but within one year after the date of purchas
e, please include check or money order for $10 U.S. (A$19 for Australia, or \'a310.00 for Europe) currency per CD or floppy disk replacement. Note: Certified mail recommended.
\par In the U.S. send to:
\par
\par Warranty Replacements
\par Activision, Inc.
\par P.O. Box 67713
\par Los Angeles, California 90067
\par
\par }\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f27\fs24\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\f1\fs20 In Europe send to:
\par }{\f1\fs20
\par WARRANTY REPLACEMENTS
\par }\pard\plain \s20\ql \li0\ri0\widctlpar\nooverflow\faauto\rin0\lin0\itap0 \fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f1\fs20\lang1033\langfe1033\langnp1033
ACTIVISION (UK) Ltd., Parliament House, St Laurence Way, Slough, Berkshire, SL1 2BW, United Kingdom.
\par }\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f27\fs24\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20 Disc Replacement: +44 (0)}{\f1\fs20\cf6 }{\f1\fs20 8705 143 525
\par
\par }{\b\f1\fs20 In Australia send to:
\par }{\f1\fs20
\par Warranty Replacements
\par Activision
\par }\pard \ql \li0\ri0\widctlpar\nooverflow\faauto\rin0\lin0\itap0 {\f1\fs20 Century Plaza}{\f1\fs20\cf0
\par }{\f1\fs20 41 Rawson Street}{\f1\fs20
\par }{\f1\fs20 Epping, NSW 2121}{\f1\fs20
\par }{\f1\fs20 Australia
\par }\pard\plain \s17\ql \li0\ri0\sb29\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f12\fs18\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20
\par LIMITATION ON DAMAGES: IN NO EVENT WILL ACTIVISION BE LIABLE FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES RESULTING FROM POSSESSION, USE OR MALFUNCTION OF THE PROGRAM, INCLUDING DAMAGES T
O PROPERTY, LOSS OF GOODWILL, COMPUTER FAILURE OR MALFUNCTION AND, TO THE EXTENT PERMITTED BY LAW, DAMAGES FOR PERSONAL INJURIES, EVEN IF ACTIVISION HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ACTIVISION\rquote
S LIABILITY SHALL NOT EXCEED THE ACTUAL PRI
CE PAID FOR THE LICENSE TO USE THIS PROGRAM. SOME STATES/COUNTRIES DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY LASTS AND/OR THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATIONS AND/OR EXCLUSION OR LIMIT
ATION OF LIABILITY MAY NOT APPLY TO YOU. THIS WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS, AND YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO JURISDICTION.
\par TERMINATION: Without prejudice to any other rights of Activision, this Agreement will terminate automatically if you fail to comply with its terms and conditions. In such event, you must destroy all copies of the Program and all of its component parts.
\par
\par U.S. GOVERNMENT RESTRICTED RIGHTS: the Program and documentation have been developed entirely at private expense and are provided as \'93Commercial Computer Software\'94 or \'93restricted computer software.\'94
Use, duplication or disclosure by the U.S. Government or a U.S. Government subcontractor is subject to the restrictions set forth in subparagraph (c)(1)
(ii) of the Rights in Technical Data and Computer Software clauses in DFARS 252.227-7013 or as set forth in subparagraph (c)(1) and (2) of the Commercial Computer Software Restricted Rights clauses at FAR 52.227-19, as applicable. The Contractor/Manufactu
rer is Activision, Inc., 3100 Ocean Park Boulevard, Santa Monica, California 90405.
\par
\par INJUNCTION: Because Activision would be irreparably damaged if the terms of this Agreement were not specifically enforced, you agree that Activision shall be entitled, with
out bond, other security or proof of damages, to appropriate equitable remedies with respect to breaches of this Agreement, in addition to such other remedies as Activision may otherwise have under applicable laws.
\par
\par INDEMNITY: You agree to indemnify, defen
d and hold Activision, its partners, licensors, affiliates, contractors, officers, directors, employees and agents harmless from all damages, losses and expenses arising directly or indirectly from your acts and omissions to act in using the Product pursu
ant to the terms of this Agreement
\par
\par MISCELLANEOUS: This Agreement represents the complete agreement concerning this license between the parties and supersedes all prior agreements and representations between them. It may be amended only by a writing execut
ed by both parties. If any provision of this Agreement is held to be unenforceable for any reason, such provision shall be reformed only to the extent necessary to make it enforceable and the remaining provisions of this Agreement shall not be affected. T
h
is Agreement shall be construed under California law as such law is applied to agreements between California residents entered into and to be performed within California, except as governed by federal law and you consent to the exclusive jurisdiction of t
he state and federal courts in Los Angeles, California.
\par
\par If you have any questions concerning this license, you may contact Activision at 3100 Ocean Park Boulevard, Santa Monica, California 90405, USA, (310) 255-2000, Attn. Business and Legal Affairs, legal@activision.com.
\par }\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f27\fs24\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20
\par }}

1496
base/maps/examples.map Normal file

File diff suppressed because it is too large Load Diff

BIN
bin/EffectsEd.exe Normal file

Binary file not shown.

BIN
bin/ModView.exe Normal file

Binary file not shown.

BIN
bin/Radiant.exe Normal file

Binary file not shown.

1
bin/RadiantMP.bat Normal file
View File

@ -0,0 +1 @@
start radiant -noNPC -noConfusEd .\sof2mp.qe4

BIN
bin/ShaderEd2.exe Normal file

Binary file not shown.

BIN
bin/SoF2Asm.exe Normal file

Binary file not shown.

BIN
bin/SoF2lcc.exe Normal file

Binary file not shown.

BIN
bin/brick.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
bin/carcass.exe Normal file

Binary file not shown.

BIN
bin/clamp.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
bin/cpp.exe Normal file

Binary file not shown.

BIN
bin/dirt.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

540
bin/entities.def Normal file
View File

@ -0,0 +1,540 @@
/*QUAKED item_***** ( 0 0 0 ) (-16 -16 -16) (16 16 16) suspended
DO NOT USE THIS CLASS, IT JUST HOLDS GENERAL INFORMATION.
The suspended flag will allow items to hang in the air, otherwise they are dropped to the next surface.
If an item is the target of another entity, it will not spawn in until fired.
An item fires all of its targets when it is picked up. If the toucher can't carry it, the targets won't be fired.
"notfree" if set to 1, don't spawn in free for all games
"notteam" if set to 1, don't spawn in team games
"notsingle" if set to 1, don't spawn in single player games
"wait" override the default wait before respawning. -1 = never respawn automatically, which can be used with targeted spawning.
"random" random number of plus or minus seconds varied from the respawn time
"count" override quantity or duration on most items.
*/
/*QUAKED pickup_armor_big (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_armor_medium (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_armor_small (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_health_big (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_health_small (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_weapon_US_SOCOM (0 .6 .6) (-15 -15 -15) (15 15 15)
Pistol, uses 45 rounds
*/
/*QUAKED pickup_weapon_M19 (0 .6 .6) (-15 -15 -15) (15 15 15)
Pistol, uses 45 rounds
*/
/*QUAKED pickup_weapon_microuzi (0 .6 .6) (-15 -15 -15) (15 15 15)
Sub-Machinegun, uses 9mm rounds
*/
/*QUAKED pickup_weapon_M3A1 (0 .6 .6) (-15 -15 -15) (15 15 15)
Sub-Machinegun, uses 45 rounds
*/
/*QUAKED pickup_weapon_USAS_12 (0 .6 .6) (-15 -15 -15) (15 15 15)
Shotgun, uses 12-gauge rounds
ammo ---------- amount of ammo (defaults to 10)
*/
/*QUAKED pickup_weapon_M590 (0 .6 .6) (-15 -15 -15) (15 15 15)
Shotgun, uses 12-gauge rounds
*/
/*QUAKED pickup_weapon_MSG90A1 (0 .6 .6) (-15 -15 -15) (15 15 15)
Sniper Rifle, uses 7.62 rounds
*/
/*QUAKED pickup_weapon_M4 (0 .6 .6) (-15 -15 -15) (15 15 15)
Assault Rifle, uses 5.56 rounds and 40mm grenades
*/
/*QUAKED pickup_weapon_AK_74 (0 .6 .6) (-15 -15 -15) (15 15 15)
Assault Rifle, uses 5.56 rounds
*/
/*QUAKED pickup_weapon_M60 (0 .6 .6) (-15 -15 -15) (15 15 15)
Machinegun, uses 7.62 rounds
*/
/*QUAKED pickup_weapon_RPG_7 (0 .6 .6) (-15 -15 -15) (15 15 15)
RPG, uses 40mm rounds
*/
/*QUAKED pickup_weapon_MM_1 (0 .6 .6) (-15 -15 -15) (15 15 15)
Grenade Launcher, uses 40mm rounds
*/
/*QUAKED pickup_weapon_M67 (0 .6 .6) (-15 -15 -15) (15 15 15)
Grenade
*/
/*QUAKED pickup_weapon_M84 (0 .6 .6) (-15 -15 -15) (15 15 15)
Grenade
*/
/*QUAKED pickup_weapon_F1 (0 .6 .6) (-15 -15 -15) (15 15 15)
Grenade
*/
/*QUAKED pickup_weapon_L2A2 (0 .6 .6) (-15 -15 -15) (15 15 15)
Grenade
*/
/*QUAKED pickup_weapon_MDN11 (0 .6 .6) (-15 -15 -15) (15 15 15)
Grenade
*/
/*QUAKED pickup_weapon_SMOHG92 (0 .6 .6) (-15 -15 -15) (15 15 15)
Grenade
*/
/*QUAKED pickup_weapon_AN_M14 (0 .6 .6) (-15 -15 -15) (15 15 15)
Incendiary Grenade
*/
/*QUAKED pickup_weapon_M15 (0 .6 .6) (-15 -15 -15) (15 15 15)
White Phosphorus Grenade
*/
/*QUAKED pickup_ammo_45 (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_ammo_9mm (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_ammo_12gauge (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_ammo_762 (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_ammo_556 (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_ammo_40mm (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_ammo_rpg7 (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED pickup_backpack (0 .6 .6) (-15 -15 -15) (15 15 15)
*/
/*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -46) (16 16 48) initial
potential spawning position for deathmatch games.
The first time a player enters the game, they will be at an 'initial' spot.
Targets will be fired when someone spawns in on them.
*/
/*QUAKED info_player_intermission (1 0 1) (-16 -16 -46) (16 16 48)
The intermission will be viewed from this point. Target an info_notnull for the view direction.
*/
/*QUAKED gametype_player (0 1 0) (-16 -16 -46) (16 16 48) REDTEAM BLUETEAM
Potential spawning position for red or blue team in custom gametype games.
*/
/*QUAKED gametype_trigger (0 0 .8) ?
*/
/*QUAKED gametype_item (0 0 1) (-16 -16 -16) (16 16 16)
"name" name of the item to spawn (defined in gametype script)
*/
/*QUAKED func_group (0 0 0) ?
Used to group brushes together just for editor convenience. They are turned into normal brushes by the utilities.
*/
/*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4)
Used as a positional target for in-game calculation, like jumppad targets.
target_position does the same thing
*/
/*QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16)
Point teleporters at these.
Now that we don't have teleport destination pads, this is just
an info_notnull
*/
/*QUAKED misc_model (1 0 0) (-16 -16 -16) (16 16 16) RMG
this model is inserted into the bsp file
"model" arbitrary .md3 file to display
*/
/*QUAKED misc_G2model (1 0 0) (-16 -16 -16) (16 16 16)
"model" arbitrary .glm file to display
*/
/*QUAKED misc_portal_surface (0 0 1) (-8 -8 -8) (8 8 8)
The portal surface nearest this entity will show a view from the targeted misc_portal_camera, or a mirror view if untargeted.
This must be within 64 world units of the surface!
*/
/*QUAKED misc_portal_camera (0 0 1) (-8 -8 -8) (8 8 8) slowrotate fastrotate noswing
The target for a misc_portal_director. You can set either angles or target another entity to determine the direction of view.
"roll" an angle modifier to orient the camera around the target vector;
*/
/*QUAKED misc_bsp (1 0 0) (-16 -16 -16) (16 16 16)
"bspmodel" arbitrary .bsp file to display
*/
/*QUAKED terrain (1.0 1.0 1.0) ?
Terrain entity
It will stretch to the full height of the brush
numPatches - integer number of patches to split the terrain brush into (default 200)
terxels - integer number of terxels on a patch side (default 4) (2 <= count <= 8)
seed - integer seed for random terrain generation (default 0)
textureScale - float scale of texture (default 0.005)
heightMap - name of heightmap data image to use
terrainDef - defines how the game textures the terrain (file is base/ext_data/*.terrain - default is grassyhills)
instanceDef - defines which bsp instances appear
miscentDef - defines which client models spawn on the terrain (file is base/ext_data/*.miscents)
densityMap - how dense the client models are packed
*/
/*QUAKED fx_play_effect (.2 .5 .8) (-8 -8 -8) (8 8 8) START_OFF
Plays specified effect file
"effect" name of .efx file
"wait" seconds between triggerings, default 0.3
"random" wait variance in seconds, default 0
"target" direction of effect, default up
"count" plays effect this many times then deletes itself, default -1 = infinite
START_OFF fx starts off
*/
/*QUAKED func_door (0 .5 .8) ? START_OPEN x CRUSHER
TOGGLE wait in both the start and end states for a trigger event.
START_OPEN the door to moves to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors).
NOMONSTER monsters will not trigger this door
"model2" .md3 model to also draw
"angle" determines the opening direction
"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
"speed" movement speed (100 default)
"wait" wait before returning (3 default, -1 = never return)
"lip" lip remaining at end of move (8 default)
"dmg" damage to inflict when blocked (2 default)
"health" if set, the door must be shot open
*/
/*QUAKED func_plat (0 .5 .8) ?
Plats are always drawn in the extended position so they will light correctly.
"lip" default 8, protrusion above rest position
"height" total height of movement, defaults to model height
"speed" overrides default 200.
"dmg" overrides default 2
"model2" .md3 model to also draw
*/
/*QUAKED func_button (0 .5 .8) ?
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.
"model2" .md3 model to also draw
"angle" determines the opening direction
"target" all entities with a matching targetname will be used
"speed" override the default 40 speed
"wait" override the default 1 second wait (-1 = never return)
"lip" override the default 4 pixel lip remaining at end of move
"health" if set, the button must be killed instead of touched
*/
/*QUAKED path_corner (.5 .3 0) (-8 -8 -8) (8 8 8)
Train path corners.
Target: next path corner and other targets to fire
"speed" speed to move to the next corner
"wait" seconds to wait before behining move to next corner
*/
/*QUAKED func_train (0 .5 .8) ? START_ON TOGGLE BLOCK_STOPS
A train is a mover that moves between path_corner target points.
Trains MUST HAVE AN ORIGIN BRUSH.
The train spawns at the first target it is pointing at.
"model2" .md3 model to also draw
"speed" default 100
"dmg" default 2
"noise" looping sound to play when the train is in motion
"target" next path corner
*/
/*QUAKED func_static (0 .5 .8) ?
A bmodel that just sits there, doing nothing. Can be used for conditional walls and models.
"model2" .md3 model to also draw
*/
/*QUAKED func_rotating (0 .5 .8) ? START_ON - X_AXIS Y_AXIS
You need to have an origin brush as part of this entity. The center of that brush will be
the point around which it is rotated. It will rotate around the Z axis by default. You can
check either the X_AXIS or Y_AXIS box to change that.
"model2" .md3 model to also draw
"speed" determines how fast it moves; default value is 100.
"dmg" damage to inflict when blocked (2 default)
*/
/*QUAKED func_bobbing (0 .5 .8) ? X_AXIS Y_AXIS
Normally bobs on the Z axis
"model2" .md3 model to also draw
"height" amplitude of bob (32 default)
"speed" seconds to complete a bob cycle (4 default)
"phase" the 0.0 to 1.0 offset in the cycle to start at
"dmg" damage to inflict when blocked (2 default)
*/
/*QUAKED func_pendulum (0 .5 .8) ?
You need to have an origin brush as part of this entity.
Pendulums always swing north / south on unrotated models. Add an angles field to the model to allow rotation in other directions.
Pendulum frequency is a physical constant based on the length of the beam and gravity.
"model2" .md3 model to also draw
"speed" the number of degrees each way the pendulum swings, (30 default)
"phase" the 0.0 to 1.0 offset in the cycle to start at
"dmg" damage to inflict when blocked (2 default)
*/
/*QUAKED func_glass (0 .5 .8) ?
Breakable glass
*/
/*QUAKED worldspawn (0 0 0) ?
Every map should have exactly one worldspawn.
"music" music wav file
"soundSet" soundset name to use (do not combine with 'noise', ignores all other flags)
"gravity" 800 is default gravity
"message" Text to print during connection process
"mission" Indicates which mission script file should be used to find the scripts for mission mode
*/
/*QUAKED model_static (1 0 0) (-16 -16 -16) (16 16 16) NO_MP
"model" arbitrary .md3 file to display
*/
/*QUAKED target_give (1 0 0) (-8 -8 -8) (8 8 8)
Gives the activator all the items pointed to.
*/
/*QUAKED target_delay (1 0 0) (-8 -8 -8) (8 8 8)
"wait" seconds to pause before firing targets.
"random" delay variance, total delay = delay +/- random seconds
*/
/*QUAKED target_score (1 0 0) (-8 -8 -8) (8 8 8)
"count" number of points to add, default 1
The activator is given this many points.
*/
/*QUAKED target_print (1 0 0) (-8 -8 -8) (8 8 8) redteam blueteam private
"message" text to print
If "private", only the activator gets the message. If no checks, all clients get the message.
*/
/*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off global activator
"noise" wav file to play
"soundSet" soundset name to use (do not combine with 'noise', ignores all other flags)
A global sound will play full volume throughout the level.
Activator sounds will play on the player that activated the target.
Global and activator sounds can't be combined with looping.
Normal sounds play each time the target is used.
Looped sounds will be toggled by use functions.
Multiple identical looping sounds will just increase volume without any speed cost.
"wait" : Seconds between auto triggerings, 0 = don't auto trigger
"random" wait variance, default is 0
"radius" radius of attenuation
*/
/*QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON
When triggered, fires a laser. You can either set a target or a direction.
*/
/*QUAKED target_teleporter (1 0 0) (-8 -8 -8) (8 8 8)
The activator will be teleported away.
*/
/*QUAKED target_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) RED_ONLY BLUE_ONLY RANDOM
This doesn't perform any actions except fire its targets.
The activator can be forced to be from a certain team.
if RANDOM is checked, only one of the targets will be fired, not all of them
*/
/*QUAKED target_kill (.5 .5 .5) (-8 -8 -8) (8 8 8)
Kills the activator.
*/
/*QUAKED target_position (0 0.5 0) (-4 -4 -4) (4 4 4)
Used as a positional target for in-game calculation, like jumppad targets.
*/
/*QUAKED target_location (0 0.5 0) (-8 -8 -8) (8 8 8)
Set "message" to the name of this location.
Closest target_location in sight used for the location, if none
in site, closest in distance
*/
/*QUAKED trigger_multiple (.5 .5 .5) ?
"wait" : Seconds between triggerings, 0.5 default, -1 = one time only.
"random" wait variance, default is 0
Variable sized repeatable trigger. Must be targeted at one or more entities.
so, the basic time between firing is a random time between
(wait - random) and (wait + random)
*/
/*QUAKED trigger_always (.5 .5 .5) (-8 -8 -8) (8 8 8)
This trigger will always fire. It is activated by the world.
*/
/*QUAKED trigger_push (.5 .5 .5) ?
Must point at a target_position, which will be the apex of the leap.
This will be client side predicted, unlike target_push
*/
/*QUAKED target_push (.5 .5 .5) (-8 -8 -8) (8 8 8) bouncepad
Pushes the activator in the direction.of angle, or towards a target apex.
"speed" defaults to 1000
if "bouncepad", play bounce noise instead of windfly
*/
/*QUAKED trigger_teleport (.5 .5 .5) ? SPECTATOR
Allows client side prediction of teleportation events.
Must point at a target_position, which will be the teleport destination.
If spectator is set, only spectators can use this teleport
Spectator teleporters are not normally placed in the editor, but are created
automatically near doors to allow spectators to move through them
*/
/*QUAKED trigger_hurt (.5 .5 .5) ? START_OFF - SILENT NO_PROTECTION SLOW
Any entity that touches this will be hurt.
It does dmg points of damage each server frame
Targeting the trigger will toggle its on / off state.
SILENT supresses playing the sound
SLOW changes the damage rate to once per second
NO_PROTECTION *nothing* stops the damage
"dmg" default 5 (whole numbers only)
*/
/*QUAKED trigger_ladder (.5 .5 .5) ?
Indicates a ladder and its normal
"angles" angle ladder faces
*/
/*QUAKED func_timer (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) START_ON
This should be renamed trigger_timer...
Repeatedly fires its targets.
Can be turned on or off by using.
"wait" base time between triggering all targets, default is 1
"random" wait variance, default is 0
so, the basic time between firing is a random time between
(wait - random) and (wait + random)
*/

BIN
bin/none.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

BIN
bin/plugins/curry.dll Normal file

Binary file not shown.

BIN
bin/plugins/gensurf.dll Normal file

Binary file not shown.

108
bin/plugins/gensurf.ini Normal file
View File

@ -0,0 +1,108 @@
[Options]
Game=0
Amplitude=128
Roughness=16
WaveLength=1024
Extents=-512,-512,512,512
CornerValues=0,0,0,0
TextureOffset=0,0
TextureScale=1,1
NH=0x0008
NV=0x0008
AddHints=0x0000
ArghRad2=0x0000
AutoOverwrite=0x0000
FixBorders=0x0001
HideBackFaces=0x0000
Plane=0x0000
Preview=0x0000
RandomSeed=0x0001
Skybox=0x0000
UseDetail=0x0000
UseLadder=0x0000
WaveType=0x0003
vid_x=0x01c7
vid_y=0x011c
view_x=0x0500
view_y=0x0000
view_cx=0x0867
view_cy=0x0400
UsePatches=0x0000
SlantAngle=0x003c
[Quake2]
OutputDir=
Texture=e1u1/grass1_4
Texture2=
Texture3=
TextureDir=c:\quake2\baseq2\textures\
UsePak=0x0000
PakFile=
LastPakFile=
GameDir=
[Half-Life]
OutputDir=
Texture=OUT_GRND1
Texture2=
Texture3=
TextureDir=
UsePak=0x0000
PakFile=
LastPakFile=
GameDir=
[SiN]
OutputDir=
Texture=generic/floor_organic/fl_grass
Texture2=
Texture3=
TextureDir=
UsePak=0x0000
PakFile=
LastPakFile=
GameDir=
[Heretic2]
OutputDir=
Texture=canyon/canyon05
Texture2=
Texture3=
TextureDir=
UsePak=0x0000
PakFile=
LastPakFile=
GameDir=
[Kingpin]
OutputDir=
Texture=bricks/s_sr_m3
Texture2=
Texture3=
TextureDir=c:\kingpin\main\textures\
UsePak=0x0000
PakFile=
LastPakFile=
GameDir=
[Genesis3D]
OutputDir=
Texture=rock13
Texture2=
Texture3=
TextureDir=
UsePak=0x0000
PakFile=
LastPakFile=
GameDir=
[Quake3]
OutputDir=
Texture=organics/grass3
Texture2=common/caulk
Texture3=
TextureDir=
UsePak=0x0000
PakFile=
LastPakFile=
GameDir=
[Bitmap]
Filename=S:\design\gensurf_images\col2.bmp
DefaultPath=S:\design\gensurf_images\
BlackValue=0
WhiteValue=256
[Formula]
Formula=256-radius/4+128*sin(radius/512)

Binary file not shown.

BIN
bin/plugins/max4/vmdexp.dle Normal file

Binary file not shown.

BIN
bin/plugins/purgeevil.dll Normal file

Binary file not shown.

BIN
bin/plugins/shapes.dll Normal file

Binary file not shown.

BIN
bin/rcc.exe Normal file

Binary file not shown.

BIN
bin/sof2data.exe Normal file

Binary file not shown.

BIN
bin/sof2map.exe Normal file

Binary file not shown.

23
bin/sof2mp.qe4 Normal file
View File

@ -0,0 +1,23 @@
{
"basepath" "..\base"
"rshcmd" ""
"remotebasepath" "..\base"
"entitypath" "__QERPATH*.def"
"texturepath" "..\base\textures"
"autosave" "..\base\maps\autosave.map"
"bsp FullVis (1/2 LMs)" "__QERPATHsof2map -bsp -rename -samplesize 32 $ -class 4 && __QERPATHsof2map -vis $ -class 2 && __QERPATHsof2map -light -extra -samplesize 32 $"
"bsp FullVis" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis $ && __QERPATHsof2map -light $"
"bsp FullVis (extra)" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis $ && __QERPATHsof2map -light -extra $"
"bsp FullVis (nolight)" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis $"
"bsp FastVis (nolight)" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis -fast $"
"bsp FastVis" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis -fast $ && __QERPATHsof2map -light $"
"bsp NoVis" "__QERPATHlocalbatch\novis.bat $"
"bsp OnlyEnts" "__QERPATHsof2map -bsp -rename -onlyents $"
"bsp Info" "__QERPATHsof2map -info $"
"bsp Relight (extra)" "__QERPATHsof2map -bsp -rename -onlyents $ && __QERPATHsof2map -light -extra $"
"bsp Relight (1/2 LM)" "__QERPATHsof2map -bsp -rename -onlyents $ && __QERPATHsof2map -light -extra -samplesize 32 $"
"brush_primit" "0"
}

23
bin/sof2mp.qe4.duplicate1 Normal file
View File

@ -0,0 +1,23 @@
{
"basepath" "..\base"
"rshcmd" ""
"remotebasepath" "..\base"
"entitypath" "__QERPATH*.def"
"texturepath" "..\base\textures"
"autosave" "..\base\maps\autosave.map"
"bsp FullVis (1/2 LMs)" "__QERPATHsof2map -bsp -rename -samplesize 32 $ -class 4 && __QERPATHsof2map -vis $ -class 2 && __QERPATHsof2map -light -extra -samplesize 32 $"
"bsp FullVis" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis $ && __QERPATHsof2map -light $"
"bsp FullVis (extra)" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis $ && __QERPATHsof2map -light -extra $"
"bsp FullVis (nolight)" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis $"
"bsp FastVis (nolight)" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis -fast $"
"bsp FastVis" "__QERPATHsof2map -bsp -rename $ && __QERPATHsof2map -vis -fast $ && __QERPATHsof2map -light $"
"bsp NoVis" "__QERPATHlocalbatch\novis.bat $"
"bsp OnlyEnts" "__QERPATHsof2map -bsp -rename -onlyents $"
"bsp Info" "__QERPATHsof2map -info $"
"bsp Relight (extra)" "__QERPATHsof2map -bsp -rename -onlyents $ && __QERPATHsof2map -light -extra $"
"bsp Relight (1/2 LM)" "__QERPATHsof2map -bsp -rename -onlyents $ && __QERPATHsof2map -light -extra -samplesize 32 $"
"brush_primit" "0"
}

BIN
bin/stucco.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

61
code/Sof2MP.dsp Normal file
View File

@ -0,0 +1,61 @@
# Microsoft Developer Studio Project File - Name="Sof2MP" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Generic Project" 0x010a
CFG=Sof2MP - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Sof2MP.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Sof2MP.mak" CFG="Sof2MP - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Sof2MP - Win32 Release" (based on "Win32 (x86) Generic Project")
!MESSAGE "Sof2MP - Win32 Debug" (based on "Win32 (x86) Generic Project")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
MTL=midl.exe
!IF "$(CFG)" == "Sof2MP - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
!ELSEIF "$(CFG)" == "Sof2MP - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
!ENDIF
# Begin Target
# Name "Sof2MP - Win32 Release"
# Name "Sof2MP - Win32 Debug"
# End Target
# End Project

149
code/Sof2MP.dsw Normal file
View File

@ -0,0 +1,149 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "SoF2cgame"=.\cgame\sof2_cgame.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "SoF2game"=.\game\sof2_game.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "SoF2ui"=.\ui\sof2_ui.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "Sof2MP"=.\Sof2MP.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name SoF2cgame
End Project Dependency
Begin Project Dependency
Project_Dep_Name SoF2game
End Project Dependency
Begin Project Dependency
Project_Dep_Name SoF2ui
End Project Dependency
Begin Project Dependency
Project_Dep_Name gt_ctf
End Project Dependency
Begin Project Dependency
Project_Dep_Name gt_dm
End Project Dependency
Begin Project Dependency
Project_Dep_Name gt_elim
End Project Dependency
Begin Project Dependency
Project_Dep_Name gt_inf
End Project Dependency
Begin Project Dependency
Project_Dep_Name gt_tdm
End Project Dependency
}}}
###############################################################################
Project: "gt_ctf"=.\gametype\gt_ctf\gt_ctf.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "gt_dm"=.\gametype\gt_dm\gt_dm.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "gt_elim"=.\gametype\gt_elim\gt_elim.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "gt_inf"=.\gametype\gt_inf\gt_inf.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "gt_tdm"=.\gametype\gt_tdm\gt_tdm.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

89
code/all.bat Normal file
View File

@ -0,0 +1,89 @@
@set include=
@del /q ..\base\vm
@cd game
call game.bat
@cd ..\cgame
call cgame.bat
@cd ..\ui
call ui.bat
@cd ..\gametype\gt_ctf
call gt_ctf.bat
@cd ..\gt_inf
call gt_inf.bat
@cd ..\gt_elim
call gt_elim.bat
@cd ..\gt_dm
call gt_dm.bat
@cd ..\gt_tdm
call gt_tdm.bat
@cd ..\..
@echo off
echo .
echo .
set bad = 0
if not exist "game\vm\sof2mp_game.qvm" goto badGame
:testcgame
if not exist "cgame\vm\sof2mp_cgame.qvm" goto badCGame
:testui
if not exist "ui\vm\sof2mp_ui.qvm" goto badUI
:testdm
if not exist "gametype\gt_dm\vm\gt_dm.qvm" goto badDM
:testtdm
if not exist "gametype\gt_tdm\vm\gt_tdm.qvm" goto badTDM
:testctf
if not exist "gametype\gt_ctf\vm\gt_ctf.qvm" goto badCTF
:testinf
if not exist "gametype\gt_inf\vm\gt_inf.qvm" goto badINF
:testelim
if not exist "gametype\gt_elim\vm\gt_elim.qvm" goto badELIM
if %bad == "0" goto goodBuild
goto end
:badGame
echo ***** SoF2MP_game.qvm did not build!
set bad = 1
goto testcgame
:badCGame
echo ***** SoF2MP_cgame.qvm did not build!
set bad = 1
goto testui
:badUI
echo ***** SoF2MP_ui.qvm did not build!
set bad = 1
goto end
:badDM
echo ***** gt_dm.qvm did not build!
set bad = 1
goto end
:badTDM
echo ***** gt_tdm.qvm did not build!
set bad = 1
goto end
:badCTF
echo ***** gt_ctf.qvm did not build!
set bad = 1
goto end
:badINF
echo ***** gt_inf.qvm did not build!
set bad = 1
goto end
:badELIM
echo ***** gt_elim.qvm did not build!
set bad = 1
goto end
:goodBuild
echo VMs were built successfully!
:end
echo .
echo .

119
code/cgame/animtable.h Normal file
View File

@ -0,0 +1,119 @@
stringID_table_t bg_animTable [MAX_ANIMATIONS+1] =
{
ENUM2STRING(BOTH_DEATH_NORMAL),
ENUM2STRING(BOTH_DEATH_NECK),
ENUM2STRING(BOTH_DEATH_CHEST_1),
ENUM2STRING(BOTH_DEATH_CHEST_2),
ENUM2STRING(BOTH_DEATH_GROIN_1),
ENUM2STRING(BOTH_DEATH_GROIN_2),
ENUM2STRING(BOTH_DEATH_GUT_1),
ENUM2STRING(BOTH_DEATH_GUT_2),
ENUM2STRING(BOTH_DEATH_HEAD_1),
ENUM2STRING(BOTH_DEATH_HEAD_2),
ENUM2STRING(BOTH_DEATH_SHOULDER_LEFT_1),
ENUM2STRING(BOTH_DEATH_SHOULDER_LEFT_2),
ENUM2STRING(BOTH_DEATH_ARMS_LEFT_1),
ENUM2STRING(BOTH_DEATH_ARMS_LEFT_2),
ENUM2STRING(BOTH_DEATH_LEGS_LEFT_1),
ENUM2STRING(BOTH_DEATH_LEGS_LEFT_2),
ENUM2STRING(BOTH_DEATH_LEGS_LEFT_3),
ENUM2STRING(BOTH_DEATH_THIGH_LEFT_1),
ENUM2STRING(BOTH_DEATH_THIGH_LEFT_2),
ENUM2STRING(BOTH_DEATH_ARMS_RIGHT_1),
ENUM2STRING(BOTH_DEATH_ARMS_RIGHT_2),
ENUM2STRING(BOTH_DEATH_LEGS_RIGHT_1),
ENUM2STRING(BOTH_DEATH_LEGS_RIGHT_2),
ENUM2STRING(BOTH_DEATH_LEGS_RIGHT_3),
ENUM2STRING(BOTH_DEATH_SHOULDER_RIGHT_1),
ENUM2STRING(BOTH_DEATH_SHOULDER_RIGHT_2),
ENUM2STRING(BOTH_DEATH_THIGH_RIGHT_1),
ENUM2STRING(BOTH_DEATH_THIGH_RIGHT_2),
ENUM2STRING(TORSO_DROP),
ENUM2STRING(TORSO_DROP_ONEHANDED),
ENUM2STRING(TORSO_DROP_KNIFE),
ENUM2STRING(TORSO_RAISE),
ENUM2STRING(TORSO_RAISE_ONEHANDED),
ENUM2STRING(TORSO_RAISE_KNIFE),
ENUM2STRING(LEGS_IDLE),
ENUM2STRING(LEGS_IDLE_CROUCH),
ENUM2STRING(LEGS_WALK),
ENUM2STRING(LEGS_WALK_BACK),
ENUM2STRING(LEGS_WALK_CROUCH),
ENUM2STRING(LEGS_WALK_CROUCH_BACK),
ENUM2STRING(LEGS_RUN),
ENUM2STRING(LEGS_RUN_BACK),
ENUM2STRING(LEGS_SWIM),
ENUM2STRING(LEGS_JUMP),
ENUM2STRING(LEGS_JUMP_BACK),
ENUM2STRING(LEGS_TURN),
ENUM2STRING(LEGS_LEAN_LEFT),
ENUM2STRING(LEGS_LEAN_RIGHT),
ENUM2STRING(LEGS_LEAN_CROUCH_LEFT),
ENUM2STRING(LEGS_LEAN_CROUCH_RIGHT),
ENUM2STRING(LEGS_LEANLEFT_WALKLEFT),
ENUM2STRING(LEGS_LEANLEFT_WALKRIGHT),
ENUM2STRING(LEGS_LEANRIGHT_WALKLEFT),
ENUM2STRING(LEGS_LEANRIGHT_WALKRIGHT),
ENUM2STRING(LEGS_LEANLEFT_CROUCH_WALKLEFT),
ENUM2STRING(LEGS_LEANLEFT_CROUCH_WALKRIGHT),
ENUM2STRING(LEGS_LEANRIGHT_CROUCH_WALKLEFT),
ENUM2STRING(LEGS_LEANRIGHT_CROUCH_WALKRIGHT),
ENUM2STRING(TORSO_IDLE_KNIFE ),
ENUM2STRING(TORSO_IDLE_PISTOL ),
ENUM2STRING(TORSO_IDLE_RIFLE ),
ENUM2STRING(TORSO_IDLE_MSG90A1_ZOOMED ),
ENUM2STRING(TORSO_IDLE_M4 ),
ENUM2STRING(TORSO_IDLE_M590 ),
ENUM2STRING(TORSO_IDLE_USAS12 ),
ENUM2STRING(TORSO_IDLE_RPG),
ENUM2STRING(TORSO_IDLE_M60),
ENUM2STRING(TORSO_IDLE_MM1),
ENUM2STRING(TORSO_IDLE_GRENADE),
ENUM2STRING(TORSO_ATTACK_KNIFE ),
ENUM2STRING(TORSO_ATTACK_KNIFE_THROW ),
ENUM2STRING(TORSO_ATTACK_PISTOL ),
ENUM2STRING(TORSO_ATTACK_RIFLE ),
ENUM2STRING(TORSO_ATTACK_MSG90A1_ZOOMED ),
ENUM2STRING(TORSO_ATTACK_M4 ),
ENUM2STRING(TORSO_ATTACK_M590 ),
ENUM2STRING(TORSO_ATTACK_USAS12 ),
ENUM2STRING(TORSO_ATTACK_RIFLEBUTT ),
ENUM2STRING(TORSO_ATTACK_RPG),
ENUM2STRING(TORSO_ATTACK_M60),
ENUM2STRING(TORSO_ATTACK_MM1),
ENUM2STRING(TORSO_ATTACK_GRENADE_START ),
ENUM2STRING(TORSO_ATTACK_GRENADE_END ),
ENUM2STRING(TORSO_ATTACK_BAYONET ),
ENUM2STRING(TORSO_ATTACK_PISTOLWHIP ),
ENUM2STRING(TORSO_RELOAD_M60),
ENUM2STRING(TORSO_RELOAD_PISTOL),
ENUM2STRING(TORSO_RELOAD_RIFLE),
ENUM2STRING(TORSO_RELOAD_MSG90A1),
ENUM2STRING(TORSO_RELOAD_RPG),
ENUM2STRING(TORSO_RELOAD_USAS12),
ENUM2STRING(TORSO_RELOAD_M590_START),
ENUM2STRING(TORSO_RELOAD_M590_SHELL),
ENUM2STRING(TORSO_RELOAD_M590_END),
ENUM2STRING(TORSO_RELOAD_MM1_START),
ENUM2STRING(TORSO_RELOAD_MM1_SHELL),
ENUM2STRING(TORSO_RELOAD_MM1_END),
//must be terminated
NULL,-1
};

576
code/cgame/cg_consolecmds.c Normal file
View File

@ -0,0 +1,576 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_consolecmds.c -- text commands typed in at the local console, or
// executed by a key binding
#include "cg_local.h"
#include "../ui/ui_shared.h"
#include "../ui/ui_public.h"
/*
=============
CG_Viewpos_f
Debugging command to print the current position
=============
*/
static void CG_Viewpos_f (void)
{
Com_Printf ("(%i %i %i) : %i\n", (int)cg.refdef.vieworg[0],
(int)cg.refdef.vieworg[1], (int)cg.refdef.vieworg[2],
(int)cg.refdef.viewangles[YAW]);
}
/*
=============
CG_ScoresDown_f
=============
*/
static void CG_ScoresDown_f( void )
{
if ( cg.scoresRequestTime + 2000 < cg.time )
{
// the scores are more than two seconds out of data,
// so request new ones
cg.scoresRequestTime = cg.time;
trap_SendClientCommand( "score" );
// leave the current scores up if they were already
// displayed, but if this is the first hit, clear them out
if ( !cg.showScores )
{
cg.showScores = qtrue;
cg.numScores = 0;
}
}
else
{
// show the cached contents even if they just pressed if it
// is within two seconds
cg.showScores = qtrue;
}
}
/*
=============
CG_ScoresUp_f
=============
*/
static void CG_ScoresUp_f( void )
{
if ( cg.showScores )
{
cg.showScores = qfalse;
cg.scoreFadeTime = cg.time;
}
}
/*
=============
CG_AutomapDown_f
=============
*/
static void CG_AutomapDown_f( void )
{
cg.showAutomap = qtrue;
}
/*
=============
CG_AutomapUp_f
=============
*/
static void CG_AutomapUp_f( void )
{
cg.showAutomap = qfalse;
}
/*
=============
CG_ReloadHud_f
=============
*/
static void CG_ReloadHud_f ( void )
{
// Reset the string table used for menus
String_Init();
// Clear all menus
Menu_Reset();
// Reload the menus
CG_LoadMenus ( "ui/hud.txt" );
}
/*
=============
CG_Radio_f
Bring up the radio menu if all the conditions are met
=============
*/
static void CG_Radio_f ( void )
{
// Only in team games
if ( !cgs.gametypeData->teams )
{
return;
}
// Not when ghosting or following
if ( cg.snap->ps.pm_flags & (PMF_FOLLOW|PMF_GHOST) )
{
return;
}
// Not when a spectator
if ( cg.snap->ps.pm_type == PM_SPECTATOR )
{
return;
}
trap_UI_SetActiveMenu ( UIMENU_RADIO );
}
/*
=============
CG_Objectives_f
Bring up the objectives menu if all the conditions are met
=============
*/
static void CG_Objectives_f ( void )
{
// Dont bother popping up the objectives dialog if there is
// no objective text
if ( !cgs.gametypeData->description )
{
return;
}
trap_UI_SetActiveMenu ( UIMENU_OBJECTIVES );
}
/*
=============
CG_Outfitting_f
Bring up the outfitting menu if all the conditions are met
=============
*/
static void CG_Outfitting_f ( void )
{
// Only allow outfitting when pickups are disabled
if ( !cgs.pickupsDisabled )
{
return;
}
trap_UI_SetActiveMenu ( UIMENU_OUTFITTING );
}
/*
=============
CG_Team_f
bring up the team selection user interface
=============
*/
static void CG_Team_f ( void )
{
// No team menu in non-team games
if ( !cgs.gametypeData->teams )
{
return;
}
// Special case which only brings up the team menu if its the clients first
// time to the objectives dialog
if ( atoi ( CG_Argv(1) ) )
{
if ( ui_info_seenobjectives.integer )
{
return;
}
}
CG_UpdateTeamCountCvars ( );
trap_Cvar_Set ( "ui_info_seenobjectives", "1" );
trap_UI_SetActiveMenu ( UIMENU_TEAM );
}
/*
=============
CG_Drop_f
Drops the selected weapon
=============
*/
void CG_Drop_f ( void )
{
char cmd[128];
int exclude;
// Cant drop when following or a ghost
if ( cg.snap->ps.pm_flags & (PMF_FOLLOW|PMF_GHOST) )
{
return;
}
// Either dead or spectating if not normal
if ( cg.predictedPlayerState.pm_type != PM_NORMAL )
{
return;
}
// Can only drop a weapon when in ready state
if ( cg.predictedPlayerState.weaponstate != WEAPON_READY )
{
return;
}
// Cant drop the knife
if( cg.weaponSelect == WP_KNIFE )
{
return;
}
// Close the menu since a weapon is being dropped
cg.weaponMenuUp = qfalse;
// Build the server command
Com_sprintf( cmd, 128, "drop %i", cg.weaponSelect );
// Go to next weapon before the current drops
exclude = cg.weaponSelect;
cg.weaponSelect = WP_M67_GRENADE;
CG_PrevWeapon ( qfalse, exclude );
// Send server comand
trap_SendClientCommand( cmd );
}
/*
=============
CG_GetOutfittingGroupFromString
Converts the given string into an outfitting group id
=============
*/
static int CG_GetOutfittingGroupFromString ( const char* str )
{
if ( Q_stricmp ( str, "primary" ) == 0 )
{
return OUTFITTING_GROUP_PRIMARY;
}
else if ( Q_stricmp ( str, "secondary" ) == 0 )
{
return OUTFITTING_GROUP_SECONDARY;
}
else if ( Q_stricmp ( str, "pistol" ) == 0 )
{
return OUTFITTING_GROUP_PISTOL;
}
else if ( Q_stricmp ( str, "grenade" ) == 0 )
{
return OUTFITTING_GROUP_GRENADE;
}
else if ( Q_stricmp ( str, "knife" ) == 0 )
{
return OUTFITTING_GROUP_KNIFE;
}
return -1;
}
/*
=============
CG_WeaponToggle_f
toggles between multiple weapons
=============
*/
static void CG_WeaponToggle_f ( void )
{
int group1;
int group2;
int weapon1;
int weapon2;
gitem_t* item;
int i;
// Get the toggle groups
group1 = CG_GetOutfittingGroupFromString ( CG_Argv(1) );
group2 = CG_GetOutfittingGroupFromString ( CG_Argv(2) );
// Invalid toggle if either is -1
if ( group1 == -1 ) // || group2 == -1 )
{
return;
}
// Make sure they have something from both of the groups
weapon1 = WP_NONE;
weapon2 = WP_NONE;
for ( i = WP_KNIFE; i < WP_NUM_WEAPONS; i ++ )
{
// Make sure this weapon is selectable.
if ( !CG_WeaponSelectable ( i, qtrue ) )
{
continue;
}
item = BG_FindWeaponItem ( i );
if ( item->outfittingGroup == group1 )
{
weapon1 = i;
}
else if ( item->outfittingGroup == group2 )
{
weapon2 = i;
}
}
// IF only one of the two weapons is available then go to it
if ( weapon1 == WP_NONE && weapon2 == WP_NONE )
{
return;
}
else if ( weapon1 == WP_NONE )
{
cg.weaponSelect = weapon2;
return;
}
else if ( weapon2 == WP_NONE )
{
cg.weaponSelect = weapon1;
return;
}
// They have both weapons, so figure out which to go to
item = BG_FindWeaponItem ( cg.weaponSelect );
if ( item->outfittingGroup == group1 )
{
cg.weaponSelect = weapon2;
}
else
{
cg.weaponSelect = weapon1;
}
}
/*
=============
CG_NextWeapon_f
selects next weapon in inventory and allows empty weapons to
be selected
=============
*/
static void CG_NextWeapon_f ( void )
{
CG_NextWeapon ( qtrue, -1 );
}
/*
=============
CG_PrevWeapon_f
selects previous weapon in inventory and allows empty weapons
to be selectd
=============
*/
static void CG_PrevWeapon_f ( void )
{
CG_PrevWeapon ( qtrue, -1 );
}
/*
=============
CG_LastWeapon_f
Selects the last weapon that was selected
=============
*/
static void CG_LastWeapon_f ( void )
{
if ( CG_WeaponSelectable ( cg.weaponLastSelect, qtrue ) )
{
int swap = cg.weaponSelect;
cg.weaponSelect = cg.weaponLastSelect;
cg.weaponLastSelect = swap;
}
}
static void CG_TellTarget_f( void ) {
int clientNum;
char command[128];
char message[128];
clientNum = CG_CrosshairPlayer();
if ( clientNum == -1 ) {
return;
}
trap_Args( message, 128 );
Com_sprintf( command, 128, "tell %i %s", clientNum, message );
trap_SendClientCommand( command );
}
static void CG_TellAttacker_f( void ) {
int clientNum;
char command[128];
char message[128];
clientNum = CG_LastAttacker();
if ( clientNum == -1 ) {
return;
}
trap_Args( message, 128 );
Com_sprintf( command, 128, "tell %i %s", clientNum, message );
trap_SendClientCommand( command );
}
/*
==================
CG_StartOrbit_f
==================
*/
static void CG_StartOrbit_f( void ) {
char var[MAX_TOKEN_CHARS];
trap_Cvar_VariableStringBuffer( "developer", var, sizeof( var ) );
if ( !atoi(var) ) {
return;
}
if (cg_cameraOrbit.value != 0) {
trap_Cvar_Set ("cg_cameraOrbit", "0");
trap_Cvar_Set("cg_thirdPerson", "0");
} else {
trap_Cvar_Set("cg_cameraOrbit", "5");
trap_Cvar_Set("cg_thirdPerson", "1");
trap_Cvar_Set("cg_thirdPersonAngle", "0");
trap_Cvar_Set("cg_thirdPersonRange", "100");
}
}
typedef struct
{
char *cmd;
void (*function)(void);
} consoleCommand_t;
static consoleCommand_t commands[] =
{
{ "testmodel", CG_TestModel_f },
{ "nextframe", CG_TestModelNextFrame_f },
{ "prevframe", CG_TestModelPrevFrame_f },
{ "nextskin", CG_TestModelNextSkin_f },
{ "prevskin", CG_TestModelPrevSkin_f },
{ "viewpos", CG_Viewpos_f },
{ "+scores", CG_ScoresDown_f },
{ "-scores", CG_ScoresUp_f },
{ "+automap", CG_AutomapDown_f },
{ "-automap", CG_AutomapUp_f },
{ "weapnext", CG_NextWeapon_f },
{ "weapprev", CG_PrevWeapon_f },
{ "weaplast", CG_LastWeapon_f },
{ "weapon", CG_Weapon_f },
{ "tell_target", CG_TellTarget_f },
{ "tell_attacker", CG_TellAttacker_f },
{ "reloadhud", CG_ReloadHud_f },
{ "startOrbit", CG_StartOrbit_f },
{ "loaddeferred", CG_LoadDeferredPlayers },
{ "drop", CG_Drop_f },
{ "weaptoggle", CG_WeaponToggle_f },
{ "ui_radio", CG_Radio_f },
{ "ui_objectives", CG_Objectives_f },
{ "ui_outfitting", CG_Outfitting_f },
{ "ui_team", CG_Team_f },
};
/*
=================
CG_ConsoleCommand
The string has been tokenized and can be retrieved with
Cmd_Argc() / Cmd_Argv()
=================
*/
qboolean CG_ConsoleCommand( void )
{
const char *cmd;
int i;
// No console commands when a map is changing
if ( cg.mMapChange )
{
return qfalse;
}
cmd = CG_Argv(0);
for ( i = 0 ; i < sizeof( commands ) / sizeof( commands[0] ) ; i++ )
{
if ( !Q_stricmp( cmd, commands[i].cmd ) )
{
commands[i].function();
return qtrue;
}
}
return qfalse;
}
/*
=================
CG_InitConsoleCommands
Let the client system know about all of our commands
so it can perform tab completion
=================
*/
void CG_InitConsoleCommands( void )
{
int i;
for ( i = 0 ; i < sizeof( commands ) / sizeof( commands[0] ) ; i++ )
{
trap_AddCommand( commands[i].cmd );
}
//
// the game server will interpret these commands, which will be automatically
// forwarded to the server after they are not recognized locally
//
trap_AddCommand ("kill");
trap_AddCommand ("say");
trap_AddCommand ("say_team");
trap_AddCommand ("tell");
trap_AddCommand ("vsay_team");
trap_AddCommand ("give");
trap_AddCommand ("god");
trap_AddCommand ("notarget");
trap_AddCommand ("noclip");
trap_AddCommand ("team");
trap_AddCommand ("follow");
trap_AddCommand ("levelshot");
#ifdef _SOF2_BOTS
trap_AddCommand ("addbot");
#endif
trap_AddCommand ("setviewpos");
trap_AddCommand ("callvote");
trap_AddCommand ("vote");
trap_AddCommand ("stats");
trap_AddCommand ("teamtask");
trap_AddCommand ("loaddeferred");
trap_AddCommand ("gametype_restart");
}

1842
code/cgame/cg_draw.c Normal file

File diff suppressed because it is too large Load Diff

421
code/cgame/cg_drawtools.c Normal file
View File

@ -0,0 +1,421 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc
#include "cg_local.h"
/*
================
CG_AdjustFrom640
Adjusted for resolution and screen aspect ratio
================
*/
void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) {
#if 0
// adjust for wide screens
if ( cgs.glconfig.vidWidth * 480 > cgs.glconfig.vidHeight * 640 ) {
*x += 0.5 * ( cgs.glconfig.vidWidth - ( cgs.glconfig.vidHeight * 640 / 480 ) );
}
#endif
// scale for screen sizes
*x *= cgs.screenXScale;
*y *= cgs.screenYScale;
*w *= cgs.screenXScale;
*h *= cgs.screenYScale;
}
/*
================
CG_FillRect
Coordinates are 640*480 virtual values
=================
*/
void CG_FillRect( float x, float y, float width, float height, const float *color ) {
trap_R_SetColor( color );
CG_AdjustFrom640( &x, &y, &width, &height );
trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, NULL, cgs.media.whiteShader );
trap_R_SetColor( NULL );
}
/*
================
CG_DrawSides
Coords are virtual 640x480
================
*/
void CG_DrawSides(float x, float y, float w, float h, float size) {
CG_AdjustFrom640( &x, &y, &w, &h );
size *= cgs.screenXScale;
trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, NULL, cgs.media.whiteShader );
trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, NULL, cgs.media.whiteShader );
}
void CG_DrawTopBottom(float x, float y, float w, float h, float size) {
CG_AdjustFrom640( &x, &y, &w, &h );
size *= cgs.screenYScale;
trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, NULL, cgs.media.whiteShader );
trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, NULL, cgs.media.whiteShader );
}
/*
================
UI_DrawRect
Coordinates are 640*480 virtual values
=================
*/
void CG_DrawRect( float x, float y, float width, float height, float size, const float *color ) {
trap_R_SetColor( color );
CG_DrawTopBottom(x, y, width, height, size);
CG_DrawSides(x, y, width, height, size);
trap_R_SetColor( NULL );
}
/*
================
CG_DrawPic
Coordinates are 640*480 virtual values
=================
*/
void CG_DrawPic( float x, float y, float width, float height, qhandle_t hShader ) {
CG_AdjustFrom640( &x, &y, &width, &height );
trap_R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, NULL, hShader );
}
/*
================
CG_DrawStretchPic
Coordinates are 640*480 virtual values
=================
*/
void CG_DrawStretchPic(
float x,
float y,
float width,
float height,
float sx,
float sy,
float sw,
float sh,
const float* color,
qhandle_t hShader
)
{
CG_AdjustFrom640( &x, &y, &width, &height );
trap_R_DrawStretchPic( x, y, width, height, sx, sy, sw, sh, NULL, hShader );
}
/*
================
CG_DrawRotatePic
Coordinates are 640*480 virtual values
A width of 0 will draw with the original image width
rotates around the upper right corner of the passed in point
=================
*/
void CG_DrawRotatePic( float x, float y, float width, float height,float angle, qhandle_t hShader ) {
CG_AdjustFrom640( &x, &y, &width, &height );
trap_R_DrawRotatePic( x, y, width, height, 0, 0, 1, 1, angle, hShader );
}
/*
================
CG_DrawRotatePic2
Coordinates are 640*480 virtual values
A width of 0 will draw with the original image width
Actually rotates around the center point of the passed in coordinates
=================
*/
void CG_DrawRotatePic2( float x, float y, float width, float height,float angle, qhandle_t hShader ) {
CG_AdjustFrom640( &x, &y, &width, &height );
trap_R_DrawRotatePic2( x, y, width, height, 0, 0, 1, 1, angle, hShader );
}
/*
=================
CG_DrawStrlen
Returns character count, skiping color escape codes
=================
*/
int CG_DrawStrlen( const char *str ) {
const char *s = str;
int count = 0;
while ( *s ) {
if ( Q_IsColorString( s ) ) {
s += 2;
} else {
count++;
s++;
}
}
return count;
}
/*
=============
CG_TileClearBox
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
static void CG_TileClearBox( int x, int y, int w, int h, qhandle_t hShader ) {
float s1, t1, s2, t2;
s1 = x/64.0;
t1 = y/64.0;
s2 = (x+w)/64.0;
t2 = (y+h)/64.0;
trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, NULL, hShader );
}
/*
==============
CG_TileClear
Clear around a sized down screen
==============
*/
void CG_TileClear( void )
{
int top, bottom, left, right;
int w, h;
w = cgs.glconfig.vidWidth;
h = cgs.glconfig.vidHeight;
if ( cg.refdef.x == 0 && cg.refdef.y == 0 &&
cg.refdef.width == w && cg.refdef.height == h ) {
return; // full screen rendering
}
top = cg.refdef.y;
bottom = top + cg.refdef.height-1;
left = cg.refdef.x;
right = left + cg.refdef.width-1;
// clear above view screen
CG_TileClearBox( 0, 0, w, top, cgs.media.backTileShader );
// clear below view screen
CG_TileClearBox( 0, bottom, w, h - bottom, cgs.media.backTileShader );
// clear left of view screen
CG_TileClearBox( 0, top, left, bottom - top + 1, cgs.media.backTileShader );
// clear right of view screen
CG_TileClearBox( right, top, w - right, bottom - top + 1, cgs.media.backTileShader );
}
/*
================
CG_FadeColor
================
*/
float *CG_FadeColor( int startMsec, int totalMsec ) {
static vec4_t color;
int t;
if ( startMsec == 0 ) {
return NULL;
}
t = cg.time - startMsec;
if ( t >= totalMsec ) {
return NULL;
}
// fade out
if ( totalMsec - t < FADE_TIME ) {
color[3] = ( totalMsec - t ) * 1.0/FADE_TIME;
} else {
color[3] = 1.0;
}
color[0] = color[1] = color[2] = 1;
return color;
}
/*
================
CG_TeamColor
================
*/
float *CG_TeamColor( int team ) {
static vec4_t red = {1, 0.2f, 0.2f, 1};
static vec4_t blue = {0.2f, 0.2f, 1, 1};
static vec4_t other = {1, 1, 1, 1};
static vec4_t spectator = {0.7f, 0.7f, 0.7f, 1};
switch ( team ) {
case TEAM_RED:
return red;
case TEAM_BLUE:
return blue;
case TEAM_SPECTATOR:
return spectator;
default:
return other;
}
}
/*
=================
CG_GetColorForHealth
=================
*/
void CG_GetColorForHealth( vec4_t color, int health, int armor )
{
int count;
int max;
VectorCopy ( colorWhite, color );
color[3] = 1.0f;
// calculate the total points of damage that can
// be sustained at the current health / armor level
if ( health <= 0 )
{
VectorCopy ( colorBlack, color );
return;
}
count = armor;
max = health * ARMOR_PROTECTION / ( 1.0 - ARMOR_PROTECTION );
if ( max < count )
{
count = max;
}
health += count;
// set the color based on health
color[0] = 1.0f;
if ( health >= 100 )
{
color[2] = 1.0f;
}
else if ( health < 66 )
{
color[2] = 0;
}
else
{
color[2] = ( health - 66 ) / 33.0;
}
if ( health > 60 )
{
color[1] = 1.0f;
}
else if ( health < 30 )
{
color[1] = 0;
}
else
{
color[1] = ( health - 30 ) / 30.0;
}
}
/*
=====================
CG_DrawText
Renders text on the screen
=====================
*/
void CG_DrawText ( float x, float y, qhandle_t font, float scale, vec4_t color, const char* text, int limit, int flags )
{
x *= cgs.screenXScale;
y *= cgs.screenYScale;
scale *= (cgs.screenXScale);
trap_R_DrawText ( (int)x, (int)y, font, scale, color, text, limit, flags );
}
/*
=====================
CG_DrawTimer
Draws a timer on the screen with the given parameters
=====================
*/
void CG_DrawTimer ( float x, float y, qhandle_t font, float scale, vec4_t color, int flags, int msec )
{
const char* s;
if ( msec )
{
int mins;
int seconds;
int tens;
qboolean neg;
// Remember the milliseconds were negative
// before making them positive again
if ( msec < 0 )
{
msec *= -1;
neg = qtrue;
}
else
{
neg = qfalse;
}
seconds = msec / 1000;
mins = seconds / 60;
seconds -= mins * 60;
tens = seconds / 10;
seconds -= tens * 10;
s = va( "%s%i:%i%i", neg?"-":"",mins, tens, seconds );
}
else
{
s = "------";
}
CG_DrawText ( x, y, font, scale, color, s, 0, flags );
}
/*
=====================
CG_DrawTextWithCursor
Renders text on the screen with a blinking cursor
=====================
*/
void CG_DrawTextWithCursor ( float x, float y, qhandle_t font, float scale, vec4_t color, const char* text, int limit, int flags, int cursorPos, char cursor )
{
x *= cgs.screenXScale;
y *= cgs.screenYScale;
scale *= (cgs.screenXScale);
trap_R_DrawTextWithCursor ( (int)x, (int)y, font, scale, color, text, limit, flags, cursorPos, cursor );
}

275
code/cgame/cg_effects.c Normal file
View File

@ -0,0 +1,275 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_effects.c -- these functions generate localentities, usually as a result
// of event processing
#include "cg_local.h"
/*
==================
CG_BubbleTrail
Bullets shot underwater
==================
*/
void CG_BubbleTrail( vec3_t start, vec3_t end, float spacing ) {
vec3_t move;
vec3_t vec;
float len;
int i;
if ( cg_noProjectileTrail.integer ) {
return;
}
VectorCopy (start, move);
VectorSubtract (end, start, vec);
len = VectorNormalize (vec);
// advance a random amount first
i = rand() % (int)spacing;
VectorMA( move, i, vec, move );
VectorScale (vec, spacing, vec);
for ( ; i < len; i += spacing ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
le->leFlags = LEF_PUFF_DONT_SCALE;
le->leType = LE_MOVE_SCALE_FADE;
le->startTime = cg.time;
le->endTime = cg.time + 1000 + random() * 250;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
re = &le->refEntity;
re->shaderTime = cg.time / 1000.0f;
re->reType = RT_SPRITE;
re->rotation = 0;
re->radius = 3;
re->customShader = cgs.media.waterBubbleShader;
re->shaderRGBA[0] = 0xff;
re->shaderRGBA[1] = 0xff;
re->shaderRGBA[2] = 0xff;
re->shaderRGBA[3] = 0xff;
le->color[3] = 1.0;
le->pos.trType = TR_LINEAR;
le->pos.trTime = cg.time;
VectorCopy( move, le->pos.trBase );
le->pos.trDelta[0] = crandom()*5;
le->pos.trDelta[1] = crandom()*5;
le->pos.trDelta[2] = crandom()*5 + 6;
VectorAdd (move, vec, move);
}
}
void CG_TestLine( vec3_t start, vec3_t end, int time, unsigned int color, int radius)
{
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
le->leType = LE_LINE;
le->startTime = cg.time;
le->endTime = cg.time + time;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
re = &le->refEntity;
VectorCopy( start, re->origin );
VectorCopy( end, re->oldorigin);
re->shaderTime = cg.time / 1000.0f;
re->reType = RT_LINE;
re->radius = 0.5*radius;
re->customShader = cgs.media.whiteShader; //trap_R_RegisterShaderNoMip("textures/colombia/canvas_doublesided");
re->shaderTexCoord[0] = re->shaderTexCoord[1] = 1.0f;
if (color==0)
{
re->shaderRGBA[0] = re->shaderRGBA[1] = re->shaderRGBA[2] = re->shaderRGBA[3] = 0xff;
}
else
{
re->shaderRGBA[0] = color & 0xff;
color >>= 8;
re->shaderRGBA[1] = color & 0xff;
color >>= 8;
re->shaderRGBA[2] = color & 0xff;
re->shaderRGBA[3] = 0xff;
}
le->color[3] = 1.0;
}
/*
==================
CG_ThrowShard
==================
*/
void CG_ThrowShard( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
re = &le->refEntity;
le->leType = LE_FRAGMENT;
le->startTime = cg.time;
le->endTime = le->startTime + 5000 + random() * 3000;
VectorCopy( origin, re->origin );
AxisCopy( axisDefault, re->axis );
re->hModel = hModel;
le->pos.trType = TR_GRAVITY;
le->angles.trType = TR_GRAVITY;
VectorCopy( origin, le->pos.trBase );
VectorCopy( velocity, le->pos.trDelta );
VectorSet(le->angles.trBase, 20, 20, 20);
VectorCopy( velocity, le->angles.trDelta );
le->pos.trTime = cg.time;
le->angles.trTime = cg.time;
le->leFlags = LEF_TUMBLE;
le->angles.trBase[YAW] = 180;
le->bounceFactor = 0.3f;
}
/*
==================
CG_GlassShatter
Throws glass shards from within a given bounding box in the world
==================
*/
void CG_GlassShatter(int entnum, vec3_t org, vec3_t mins, vec3_t maxs)
{
vec3_t velocity, a, shardorg, dif, difx;
float windowmass;
float shardsthrow = 0;
trap_S_StartSound(org, entnum, CHAN_BODY, cgs.media.glassBreakSound, -1, -1 );
VectorSubtract(maxs, mins, a);
windowmass = VectorLength(a); //should give us some idea of how big the chunk of glass is
while (shardsthrow < windowmass)
{
velocity[0] = crandom()*150;
velocity[1] = crandom()*150;
velocity[2] = 150 + crandom()*75;
VectorCopy(org, shardorg);
dif[0] = (maxs[0]-mins[0])/2;
dif[1] = (maxs[1]-mins[1])/2;
dif[2] = (maxs[2]-mins[2])/2;
if (dif[0] < 2)
{
dif[0] = 2;
}
if (dif[1] < 2)
{
dif[1] = 2;
}
if (dif[2] < 2)
{
dif[2] = 2;
}
difx[0] = (float) Q_irand(1, (int)((dif[0]*0.9)*2));
difx[1] = (float) Q_irand(1, (int)((dif[1]*0.9)*2));
difx[2] = (float) Q_irand(1, (int)((dif[2]*0.9)*2));
if (difx[0] > dif[0])
{
shardorg[0] += difx[0]-(dif[0]);
}
else
{
shardorg[0] -= difx[0];
}
if (difx[1] > dif[1])
{
shardorg[1] += difx[1]-(dif[1]);
}
else
{
shardorg[1] -= difx[1];
}
if (difx[2] > dif[2])
{
shardorg[2] += difx[2]-(dif[2]);
}
else
{
shardorg[2] -= difx[2];
}
trap_FX_PlayEffectID( cgs.media.glassChunkEffect, shardorg, velocity, -1, -1 );
shardsthrow += 20;
}
}
qboolean CG_PointLineIntersect ( vec3_t start, vec3_t end, vec3_t point, float rad, vec3_t intersection )
{
vec3_t dir;
vec3_t distance;
float len;
float lineSize;
VectorSubtract ( end, start, dir );
lineSize = VectorNormalize ( dir );
// Calculate the distnace from the shooter to the target
VectorSubtract ( point, start, distance );
// Use that distnace to determine the point of tangent in relation to
// the center of the player entity
VectorMA ( start, DotProduct ( dir, distance ), dir, intersection );
VectorSubtract ( intersection, point, distance );
len = VectorLengthSquared ( distance );
// Is the intersection point within the given radius requirements?
if ( len < rad * rad )
{
// Make sure its not past the end of the given line
VectorSubtract ( intersection, start, distance );
len = VectorLengthSquared ( distance );
// If the len
if ( len < lineSize * lineSize )
{
return qtrue;
}
}
return qfalse;
}
void CG_BulletFlyBySound ( vec3_t start, vec3_t end )
{
// make the incidental sounds - all of these should already be precached on the server
vec3_t soundPoint;
if( CG_PointLineIntersect(start, end, cg.refdef.vieworg, 100, soundPoint ) )
{
if (irand(1, 10) < 5)
{
int which = irand(0, NUMFLYBYS - 1);
trap_S_StartSound (soundPoint, cg.predictedPlayerState.clientNum, CHAN_AUTO, cgs.media.flybySounds[which], -1, -1 );
}
}
}

1049
code/cgame/cg_ents.c Normal file

File diff suppressed because it is too large Load Diff

1195
code/cgame/cg_event.c Normal file

File diff suppressed because it is too large Load Diff

97
code/cgame/cg_gametype.c Normal file
View File

@ -0,0 +1,97 @@
// Copyright (C) 2001-2002 Raven Software
//
// cg_gametype.c -- dynamic gametype handling
#include "cg_local.h"
/*
===============
CG_ParseGametypeItems
===============
*/
qboolean CG_ParseGametypeItems ( TGPGroup itemsGroup )
{
TGPGroup itemGroup;
int itemCount;
char temp[MAX_QPATH];
// Handle NULL for convienience
if ( !itemsGroup )
{
return qfalse;
}
// Loop over all the items and add each
itemGroup = trap_GPG_GetSubGroups ( itemsGroup );
itemCount = 0;
while ( itemGroup )
{
// Parse icon file
trap_GPG_FindPairValue ( itemGroup, "icon", "", temp );
bg_itemlist[ MODELINDEX_GAMETYPE_ITEM + itemCount ].icon = (char *)trap_VM_LocalStringAlloc ( temp );
// Parse display name file
trap_GPG_FindPairValue ( itemGroup, "displayname", "", temp );
bg_itemlist[ MODELINDEX_GAMETYPE_ITEM + itemCount ].pickup_name = (char *)trap_VM_LocalStringAlloc ( temp );
// Parse world model file
trap_GPG_FindPairValue ( itemGroup, "model", "", temp );
bg_itemlist[ MODELINDEX_GAMETYPE_ITEM + itemCount ].world_model[0] = (char *)trap_VM_LocalStringAlloc ( temp );
// Parse bolt model file
trap_GPG_FindPairValue ( itemGroup, "boltmodel", "", temp );
trap_G2API_InitGhoul2Model(&cg_items[MODELINDEX_GAMETYPE_ITEM+itemCount].boltModel, temp, 0 , 0, 0, 0, 0);
cg_items[MODELINDEX_GAMETYPE_ITEM+itemCount].radius[0] = 60;
CG_RegisterItemVisuals ( MODELINDEX_GAMETYPE_ITEM+itemCount );
itemCount++;
// Next sub group
itemGroup = trap_GPG_GetNext(itemGroup);
}
return qtrue;
}
/*
===============
CG_ParseGametypeFile
===============
*/
qboolean CG_ParseGametypeFile ( void )
{
TGenericParser2 GP2;
TGPGroup topGroup;
TGPGroup gametypeGroup;
// Open the given gametype file
GP2 = trap_GP_ParseFile ( (char*)cgs.gametypeData->script, qtrue, qfalse );
if (!GP2)
{
return qfalse;
}
// Grab the top group and the list of sub groups
topGroup = trap_GP_GetBaseParseGroup(GP2);
gametypeGroup = trap_GPG_FindSubGroup(topGroup, "gametype" );
if ( !gametypeGroup )
{
trap_GP_Delete(&GP2);
return qfalse;
}
// Mainly interested in the items within the file
CG_ParseGametypeItems ( trap_GPG_FindSubGroup ( gametypeGroup, "items" ) );
// Free up the parser
trap_GP_Delete(&GP2);
// Defaults
trap_Cvar_Set ( "ui_blueteamname", "Blue Team" );
trap_Cvar_Set ( "ui_redteamname", "Red Team" );
return qtrue;
}

1454
code/cgame/cg_gore.c Normal file

File diff suppressed because it is too large Load Diff

318
code/cgame/cg_info.c Normal file
View File

@ -0,0 +1,318 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_info.c -- display information while data is being loading
#include "cg_local.h"
#define MAX_LOADING_PLAYER_ICONS 16
#define MAX_LOADING_ITEM_ICONS 26
static int loadingPlayerIconCount;
static int loadingItemIconCount;
static qhandle_t loadingPlayerIcons[MAX_LOADING_PLAYER_ICONS];
static qhandle_t loadingItemIcons[MAX_LOADING_ITEM_ICONS];
void CG_LoadBar(void);
/*
======================
CG_LoadingStage
======================
*/
void CG_LoadingStage ( int stage )
{
if ( !cg.loading )
{
return;
}
cg.loadStage = stage;
if ( cg.loadStage )
{
trap_UpdateScreen();
}
}
/*
======================
CG_LoadingString
======================
*/
void CG_LoadingString( const char *s )
{
if ( !cg.loading )
{
return;
}
Q_strncpyz( cg.infoScreenText, s, sizeof( cg.infoScreenText ) );
trap_UpdateScreen();
}
/*
===================
CG_LoadingItem
===================
*/
void CG_LoadingItem( int itemNum )
{
gitem_t *item;
if ( !cg.loading )
{
return;
}
item = &bg_itemlist[itemNum];
if ( item->icon && loadingItemIconCount < MAX_LOADING_ITEM_ICONS ) {
loadingItemIcons[loadingItemIconCount++] = trap_R_RegisterShaderNoMip( item->icon );
}
CG_LoadingString( item->pickup_name );
}
/*
===================
CG_LoadingClient
===================
*/
void CG_LoadingClient( int clientNum )
{
const char *info;
char personality[MAX_QPATH];
if ( !cg.loading )
{
return;
}
info = CG_ConfigString( CS_PLAYERS + clientNum );
Q_strncpyz( personality, Info_ValueForKey( info, "n" ), sizeof(personality) );
Q_CleanStr( personality );
CG_LoadingString( personality );
}
/*
====================
CG_DrawInformation
Draw all the status / pacifier stuff during level loading
====================
*/
void CG_DrawInformation( void )
{
static qhandle_t levelshot = 0;
static char levelshotShader[MAX_QPATH] = "";
const char *s;
const char *info;
const char *sysInfo;
char shader[MAX_QPATH];
int y;
int value;
qhandle_t overlay;
char buf[1024];
// As long as the map change flag is set we draw the map change screen
if ( cg.mMapChange )
{
CG_DrawMapChange ( );
return;
}
info = CG_ConfigString( CS_SERVERINFO );
sysInfo = CG_ConfigString( CS_SYSTEMINFO );
if ( cg.mInRMG )
{
const char* terrainInfo;
terrainInfo = CG_ConfigString( CS_TERRAINS + 1 );
if ( terrainInfo )
{
s = Info_ValueForKey ( terrainInfo, "terraindef" );
Com_sprintf ( shader, sizeof(shader), "gfx/menus/levelshots/mp_rmg_%s", s );
}
else
{
Com_sprintf ( shader, sizeof(shader), "gfx/menus/levelshots/unknownmap_mp" );
}
}
else
{
s = Info_ValueForKey( info, "mapname" );
Com_sprintf ( shader, sizeof(shader), "gfx/menus/levelshots/%s", s );
}
if ( Q_stricmp ( levelshotShader, shader ) )
{
levelshot = trap_R_RegisterShaderNoMip( shader );
Com_sprintf ( levelshotShader, sizeof(levelshotShader), shader );
}
overlay = trap_R_RegisterShaderNoMip( "gfx/menus/levelshots/unknownmap_mp" );
// Draw the level shot
trap_R_SetColor( NULL );
if ( levelshot )
{
vec4_t fade;
fade[0] = 1.0f;
fade[1] = 1.0f;
fade[2] = 1.0f;
fade[3] = 1.0f - ((float)cg.loadStage / 15.0f);
CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, levelshot );
trap_R_SetColor ( fade );
CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, overlay );
trap_R_SetColor ( NULL );
}
else
{
CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, overlay );
}
// Draw the progress bar
CG_LoadBar();
// Determine the string to print
if ( cg.infoScreenText[0] )
{
s = va("Loading... %s", cg.infoScreenText);
}
else
{
s = "Awaiting snapshot...";
}
// Render the string
CG_DrawText( 320 - trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.53f, 0 ) / 2, 198 - 32,
cgs.media.hudFont, 0.53f, colorWhite, s, 0, 0 );
// draw info string information
y = 250-32;
// don't print server lines if playing a local game
trap_Cvar_VariableStringBuffer( "sv_running", buf, sizeof( buf ) );
if ( !atoi( buf ) )
{
// server hostname
Q_strncpyz(buf, Info_ValueForKey( info, "sv_hostname" ), 1024);
Q_CleanStr(buf);
CG_DrawText ( 320 - trap_R_GetTextWidth ( buf, cgs.media.hudFont, 0.53f, 0 ) / 2, y,
cgs.media.hudFont, 0.53f, colorWhite, buf, 0, 0 );
y += PROP_HEIGHT;
// pure server
s = Info_ValueForKey( sysInfo, "sv_pure" );
if ( atoi(s) )
{
s = "Pure Server";
CG_DrawText( 320 - trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.53f, 0 ) / 2, y,
cgs.media.hudFont, 0.53f, colorWhite, s, 0, 0 );
y += PROP_HEIGHT;
}
// server-specific message of the day
s = CG_ConfigString( CS_MOTD );
if ( s[0] )
{
CG_DrawText ( 320 - trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.53f, 0 ) / 2, y,
cgs.media.hudFont, 0.53f, colorWhite, s, 0, 0 );
y += PROP_HEIGHT;
}
// some extra space after hostname and motd
y += 10;
}
// map-specific message (long map name)
s = CG_ConfigString( CS_MESSAGE );
if ( s[0] )
{
CG_DrawText ( 320 - trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.53f, 0 ) / 2, y,
cgs.media.hudFont, 0.53f, colorWhite, s, 0, 0 );
y += PROP_HEIGHT;
}
// cheats warning
s = Info_ValueForKey( sysInfo, "sv_cheats" );
if ( s[0] == '1' )
{
s = "CHEATS ARE ENABLED";
CG_DrawText ( 320 - trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.53f, 0 ) / 2, y,
cgs.media.hudFont, 0.53f, colorWhite, s, 0, 0 );
y += PROP_HEIGHT;
cg.cheats = qtrue;
}
else
cg.cheats = qfalse;
s = cgs.gametypeData->displayName;
CG_DrawText ( 320 - trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.53f, 0 ) / 2, y,
cgs.media.hudFont, 0.53f, colorWhite, s, 0, 0 );
y += PROP_HEIGHT;
value = atoi( Info_ValueForKey( info, "timelimit" ) );
if ( value )
{
s = va( "Timelimit %i", value );
CG_DrawText ( 320 - trap_R_GetTextWidth( s, cgs.media.hudFont, 0.53f, 0 ) / 2, y,
cgs.media.hudFont, 0.53f, colorWhite, s, 0, 0 );
y += PROP_HEIGHT;
}
value = atoi( Info_ValueForKey( info, "scorelimit" ) );
if ( value )
{
s = va( "Scorelimit %i", value );
CG_DrawText ( 320 - trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.53f, 0 ) / 2, y,
cgs.media.hudFont, 0.53f, colorWhite, s, 0, 0 );
y += PROP_HEIGHT;
}
}
/*
===================
CG_LoadBar
===================
*/
#define LOADBAR_CLIP_WIDTH 256
#define LOADBAR_CLIP_HEIGHT 64
#define LOADBAR_BULLET_WIDTH 16
#define LOADBAR_BULLET_HEIGHT 64
void CG_LoadBar(void)
{
int x,y,i;
y = 50;
x = (640 - LOADBAR_CLIP_WIDTH) / 2;
for (i=0;i < cg.loadStage; i++ )
{
CG_DrawPic(x + (i*LOADBAR_BULLET_WIDTH), y, LOADBAR_BULLET_WIDTH, LOADBAR_BULLET_HEIGHT, cgs.media.loadBulletShader );
}
CG_DrawPic ( x, y, LOADBAR_CLIP_WIDTH, LOADBAR_CLIP_HEIGHT, cgs.media.loadClipShader );
}

89
code/cgame/cg_light.c Normal file
View File

@ -0,0 +1,89 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_light.c
#include "cg_local.h"
#if !defined(CG_LIGHTS_H_INC)
#include "cg_lights.h"
#endif
static clightstyle_t cl_lightstyle[MAX_LIGHT_STYLES];
static int lastofs;
/*
================
FX_ClearLightStyles
================
*/
void CG_ClearLightStyles (void)
{
int i;
memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
lastofs = -1;
for(i=0;i<MAX_LIGHT_STYLES*3;i++)
{
CG_SetLightstyle (i);
}
}
/*
================
FX_RunLightStyles
================
*/
void CG_RunLightStyles (void)
{
int ofs;
int i;
clightstyle_t *ls;
ofs = cg.time / 50;
// if (ofs == lastofs)
// return;
lastofs = ofs;
for (i=0,ls=cl_lightstyle ; i<MAX_LIGHT_STYLES ; i++, ls++)
{
if (!ls->length)
{
ls->value[0] = ls->value[1] = ls->value[2] = ls->value[3] = 255;
}
else if (ls->length == 1)
{
ls->value[0] = ls->map[0][0];
ls->value[1] = ls->map[0][1];
ls->value[2] = ls->map[0][2];
ls->value[3] = 255; //ls->map[0][3];
}
else
{
ls->value[0] = ls->map[ofs%ls->length][0];
ls->value[1] = ls->map[ofs%ls->length][1];
ls->value[2] = ls->map[ofs%ls->length][2];
ls->value[3] = 255; //ls->map[ofs%ls->length][3];
}
trap_R_SetLightStyle(i, *(int*)ls->value);
}
}
void CG_SetLightstyle (int i)
{
const char *s;
int j, k;
s = CG_ConfigString( i+CS_LIGHT_STYLES );
j = strlen (s);
if (j >= MAX_QPATH)
{
Com_Error (ERR_DROP, "svc_lightstyle length=%i", j);
}
cl_lightstyle[(i/3)].length = j;
for (k=0 ; k<j ; k++)
{
cl_lightstyle[(i/3)].map[k][(i%3)] = (float)(s[k]-'a')/(float)('z'-'a') * 255.0;
}
}

20
code/cgame/cg_lights.h Normal file
View File

@ -0,0 +1,20 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_lights.h --
#pragma once
#if !defined(CG_LIGHTS_H_INC)
#define CG_LIGHTS_H_INC
typedef struct
{
int length;
color4ub_t value;
color4ub_t map[MAX_QPATH];
} clightstyle_t;
void CG_ClearLightStyles (void);
void CG_RunLightStyles (void);
void CG_SetLightstyle (int i);
#endif // CG_LIGHTS_H_INC

1446
code/cgame/cg_local.h Normal file

File diff suppressed because it is too large Load Diff

594
code/cgame/cg_localents.c Normal file
View File

@ -0,0 +1,594 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_localents.c -- every frame, generate renderer commands for locally
// processed entities, like smoke puffs, shells, etc.
#include "cg_local.h"
#define MAX_LOCAL_ENTITIES 512
localEntity_t cg_localEntities[MAX_LOCAL_ENTITIES];
localEntity_t cg_activeLocalEntities; // double linked list
localEntity_t *cg_freeLocalEntities; // single linked list
/*
===================
CG_InitLocalEntities
This is called at startup and for map restarts
===================
*/
void CG_InitLocalEntities( void )
{
int i;
memset( cg_localEntities, 0, sizeof( cg_localEntities ) );
cg_activeLocalEntities.next = &cg_activeLocalEntities;
cg_activeLocalEntities.prev = &cg_activeLocalEntities;
cg_freeLocalEntities = cg_localEntities;
for ( i = 0 ; i < MAX_LOCAL_ENTITIES - 1 ; i++ )
{
cg_localEntities[i].next = &cg_localEntities[i+1];
}
}
/*
==================
CG_FreeLocalEntity
==================
*/
void CG_FreeLocalEntity( localEntity_t *le )
{
if ( !le->prev )
{
Com_Error( ERR_FATAL, "CG_FreeLocalEntity: not active" );
}
if (le->refEntity.ghoul2)
{
trap_G2API_CleanGhoul2Models(&le->refEntity.ghoul2);
}
// remove from the doubly linked active list
le->prev->next = le->next;
le->next->prev = le->prev;
// the free list is only singly linked
le->next = cg_freeLocalEntities;
cg_freeLocalEntities = le;
}
/*
===================
CG_AllocLocalEntity
Will allways succeed, even if it requires freeing an old active entity
===================
*/
localEntity_t *CG_AllocLocalEntity( void ) {
localEntity_t *le;
if ( !cg_freeLocalEntities ) {
// no free entities, so free the one at the end of the chain
// remove the oldest active entity
CG_FreeLocalEntity( cg_activeLocalEntities.prev );
}
le = cg_freeLocalEntities;
cg_freeLocalEntities = cg_freeLocalEntities->next;
memset( le, 0, sizeof( *le ) );
// link into the active list
le->next = cg_activeLocalEntities.next;
le->prev = &cg_activeLocalEntities;
cg_activeLocalEntities.next->prev = le;
cg_activeLocalEntities.next = le;
return le;
}
/*
====================================================================================
FRAGMENT PROCESSING
A fragment localentity interacts with the environment in some way (hitting walls),
or generates more localentities along a trail.
====================================================================================
*/
/*
================
CG_FragmentBounceMark
================
*/
void CG_FragmentBounceMark( localEntity_t *le, trace_t *trace ) {
int radius;
if ( le->leMarkType == LEMT_BLOOD )
{
radius = 16 + (rand()&31);
trap_R_AddDecalToScene ( cgs.media.bloodMarkShader, trace->endpos,
trace->plane.normal, random()*360,
1,1,1,1, qtrue, radius, qfalse );
}
else if ( le->leMarkType == LEMT_BURN )
{
radius = 8 + (rand()&15);
trap_R_AddDecalToScene ( cgs.media.burnMarkShader, trace->endpos,
trace->plane.normal, random()*360,
1,1,1,1, qtrue, radius, qfalse );
}
// don't allow a fragment to make multiple marks, or they
// pile up while settling
le->leMarkType = LEMT_NONE;
}
/*
================
CG_FragmentBounceSound
================
*/
void CG_FragmentBounceSound( localEntity_t *le, trace_t *trace )
{
if ( le->leBounceSoundType == LEBS_BRASS )
{
}
// don't allow a fragment to make multiple bounce sounds,
// or it gets too noisy as they settle
le->leBounceSoundType = LEBS_NONE;
}
/*
================
CG_ReflectVelocity
================
*/
void CG_ReflectVelocity( localEntity_t *le, trace_t *trace ) {
vec3_t velocity;
float dot;
int hitTime;
// reflect the velocity on the trace plane
hitTime = cg.time - cg.frametime + cg.frametime * trace->fraction;
BG_EvaluateTrajectoryDelta( &le->pos, hitTime, velocity );
dot = DotProduct( velocity, trace->plane.normal );
VectorMA( velocity, -2*dot, trace->plane.normal, le->pos.trDelta );
VectorScale( le->pos.trDelta, le->bounceFactor, le->pos.trDelta );
VectorCopy( trace->endpos, le->pos.trBase );
le->pos.trTime = cg.time;
// check for stop, making sure that even on low FPS systems it doesn't bobble
if ( trace->allsolid ||
( trace->plane.normal[2] > 0 &&
( le->pos.trDelta[2] < 40 || le->pos.trDelta[2] < -cg.frametime * le->pos.trDelta[2] ) ) ) {
le->pos.trType = TR_STATIONARY;
} else {
}
}
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) {
vec3_t newOrigin;
trace_t trace;
if ( le->pos.trType == TR_STATIONARY ) {
// sink into the ground if near the removal time
int t;
float oldZ;
t = le->endTime - cg.time;
if ( t < SINK_TIME ) {
// we must use an explicit lighting origin, otherwise the
// lighting would be lost as soon as the origin went
// into the ground
VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
oldZ = le->refEntity.origin[2];
le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
trap_R_AddRefEntityToScene( &le->refEntity );
le->refEntity.origin[2] = oldZ;
} else {
trap_R_AddRefEntityToScene( &le->refEntity );
}
return;
}
// calculate new position
BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );
// trace a line from previous position to new position
CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
if ( trace.fraction == 1.0 ) {
// still in free fall
VectorCopy( newOrigin, le->refEntity.origin );
if ( le->leFlags & LEF_TUMBLE ) {
vec3_t angles;
BG_EvaluateTrajectory( &le->angles, cg.time, angles );
AnglesToAxis( angles, le->refEntity.axis );
}
trap_R_AddRefEntityToScene( &le->refEntity );
return;
}
// if it is in a nodrop zone, remove it
// this keeps gibs from waiting at the bottom of pits of death
// and floating levels
if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP )
{
CG_FreeLocalEntity( le );
return;
}
if (!trace.startsolid)
{
// leave a mark
CG_FragmentBounceMark( le, &trace );
// do a bouncy sound
CG_FragmentBounceSound( le, &trace );
// reflect the velocity on the trace plane
CG_ReflectVelocity( le, &trace );
trap_R_AddRefEntityToScene( &le->refEntity );
}
}
/*
=====================================================================
TRIVIAL LOCAL ENTITIES
These only do simple scaling or modulation before passing to the renderer
=====================================================================
*/
/*
====================
CG_AddFadeRGB
====================
*/
void CG_AddFadeRGB( localEntity_t *le ) {
refEntity_t *re;
float c;
re = &le->refEntity;
c = ( le->endTime - cg.time ) * le->lifeRate;
c *= 0xff;
re->shaderRGBA[0] = le->color[0] * c;
re->shaderRGBA[1] = le->color[1] * c;
re->shaderRGBA[2] = le->color[2] * c;
re->shaderRGBA[3] = le->color[3] * c;
trap_R_AddRefEntityToScene( re );
}
/*
==================
CG_AddMoveScaleFade
==================
*/
static void CG_AddMoveScaleFade( localEntity_t *le ) {
refEntity_t *re;
float c;
vec3_t delta;
float len;
re = &le->refEntity;
if ( le->fadeInTime > le->startTime && cg.time < le->fadeInTime ) {
// fade / grow time
c = 1.0 - (float) ( le->fadeInTime - cg.time ) / ( le->fadeInTime - le->startTime );
}
else {
// fade / grow time
c = ( le->endTime - cg.time ) * le->lifeRate;
}
re->shaderRGBA[3] = 0xff * c * le->color[3];
if ( !( le->leFlags & LEF_PUFF_DONT_SCALE ) ) {
re->radius = le->radius * ( 1.0 - c ) + 8;
}
BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );
// if the view would be "inside" the sprite, kill the sprite
// so it doesn't add too much overdraw
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
len = VectorLength( delta );
if ( len < le->radius ) {
CG_FreeLocalEntity( le );
return;
}
trap_R_AddRefEntityToScene( re );
}
/*
===================
CG_AddScaleFade
For rocket smokes that hang in place, fade out, and are
removed if the view passes through them.
There are often many of these, so it needs to be simple.
===================
*/
static void CG_AddScaleFade( localEntity_t *le ) {
refEntity_t *re;
float c;
vec3_t delta;
float len;
re = &le->refEntity;
// fade / grow time
c = ( le->endTime - cg.time ) * le->lifeRate;
re->shaderRGBA[3] = 0xff * c * le->color[3];
re->radius = le->radius * ( 1.0 - c ) + 8;
// if the view would be "inside" the sprite, kill the sprite
// so it doesn't add too much overdraw
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
len = VectorLength( delta );
if ( len < le->radius ) {
CG_FreeLocalEntity( le );
return;
}
trap_R_AddRefEntityToScene( re );
}
/*
=================
CG_AddFallScaleFade
This is just an optimized CG_AddMoveScaleFade
For blood mists that drift down, fade out, and are
removed if the view passes through them.
There are often 100+ of these, so it needs to be simple.
=================
*/
static void CG_AddFallScaleFade( localEntity_t *le ) {
refEntity_t *re;
float c;
vec3_t delta;
float len;
re = &le->refEntity;
// fade time
c = ( le->endTime - cg.time ) * le->lifeRate;
re->shaderRGBA[3] = 0xff * c * le->color[3];
re->origin[2] = le->pos.trBase[2] - ( 1.0 - c ) * le->pos.trDelta[2];
re->radius = le->radius * ( 1.0 - c ) + 16;
// if the view would be "inside" the sprite, kill the sprite
// so it doesn't add too much overdraw
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
len = VectorLength( delta );
if ( len < le->radius ) {
CG_FreeLocalEntity( le );
return;
}
trap_R_AddRefEntityToScene( re );
}
/*
===================
CG_AddRefEntity
===================
*/
void CG_AddRefEntity( localEntity_t *le )
{
if (le->endTime < cg.time)
{
CG_FreeLocalEntity( le );
return;
}
trap_R_AddRefEntityToScene( &le->refEntity );
}
/*
===================
CG_AddLine
===================
*/
void CG_AddLine( localEntity_t *le )
{
refEntity_t *re;
re = &le->refEntity;
re->reType = RT_LINE;
trap_R_AddRefEntityToScene( re );
}
/*
================
CG_AddGib
================
*/
void CG_AddGib( localEntity_t *le ) {
vec3_t newOrigin;
trace_t trace;
if ( le->pos.trType == TR_STATIONARY ) {
// sink into the ground if near the removal time
int t;
float oldZ;
le->refEntity.origin[2] += le->zOffset;
t = le->endTime - cg.time;
if ( t < SINK_TIME ) {
// we must use an explicit lighting origin, otherwise the
// lighting would be lost as soon as the origin went
// into the ground
VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
oldZ = le->refEntity.origin[2];
le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
trap_R_AddRefEntityToScene( &le->refEntity );
le->refEntity.origin[2] = oldZ;
} else {
trap_R_AddRefEntityToScene( &le->refEntity );
}
le->refEntity.origin[2] -= le->zOffset;
return;
}
// calculate new position
BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );
// trace a line from previous position to new position
CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
if ( trace.fraction == 1.0 ) {
// still in free fall
VectorCopy( newOrigin, le->refEntity.origin );
if ( le->leFlags & LEF_TUMBLE ) {
vec3_t angles;
BG_EvaluateTrajectory( &le->angles, cg.time, angles );
AnglesToAxis( angles, le->refEntity.axis );
}
le->refEntity.origin[2] += le->zOffset;
trap_R_AddRefEntityToScene( &le->refEntity );
le->refEntity.origin[2] -= le->zOffset;
return;
}
// if it is in a nodrop zone, remove it
// this keeps gibs from waiting at the bottom of pits of death
// and floating levels
if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP )
{
CG_FreeLocalEntity( le );
return;
}
if (!trace.startsolid)
{
// leave a mark
// CG_FragmentBounceMark( le, &trace );
// do a bouncy sound
// CG_FragmentBounceSound( le, &trace );
// reflect the velocity on the trace plane
CG_ReflectVelocity( le, &trace );
le->refEntity.origin[2] += le->zOffset;
trap_R_AddRefEntityToScene( &le->refEntity );
le->refEntity.origin[2] -= le->zOffset;
}
}
//==============================================================================
/*
===================
CG_AddLocalEntities
===================
*/
void CG_AddLocalEntities( void )
{
localEntity_t *le, *next;
// walk the list backwards, so any new local entities generated
// (trails, marks, etc) will be present this frame
le = cg_activeLocalEntities.prev;
for ( ; le != &cg_activeLocalEntities ; le = next )
{
// grab next now, so if the local entity is freed we
// still have it
next = le->prev;
if ( cg.time >= le->endTime )
{
CG_FreeLocalEntity( le );
continue;
}
switch ( le->leType )
{
default:
Com_Error( ERR_FATAL, "Bad leType: %i", le->leType );
break;
case LE_FRAGMENT:
CG_AddFragment( le );
break;
case LE_MOVE_SCALE_FADE:
CG_AddMoveScaleFade( le );
break;
case LE_FADE_RGB:
CG_AddFadeRGB( le );
break;
case LE_FALL_SCALE_FADE:
CG_AddFallScaleFade( le );
break;
case LE_SCALE_FADE:
CG_AddScaleFade( le );
break;
case LE_SHOWREFENTITY:
CG_AddRefEntity( le );
break;
case LE_LINE:
CG_AddLine( le );
break;
case LE_GIB:
CG_AddGib(le);
break;
}
}
}

1953
code/cgame/cg_main.c Normal file

File diff suppressed because it is too large Load Diff

0
code/cgame/cg_media.h Normal file
View File

77
code/cgame/cg_miscents.c Normal file
View File

@ -0,0 +1,77 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_miscents.h --
#include "cg_local.h"
#define MAX_MISC_ENTS 4000
static refEntity_t *MiscEnts = 0;
static float *Radius = 0;
static int NumMiscEnts = 0;
void CG_MiscEnt(void)
{
int modelIndex;
refEntity_t *RefEnt;
TCGMiscEnt *data = (TCGMiscEnt *)cg.sharedBuffer;
vec3_t mins, maxs;
float *radius;
if (NumMiscEnts >= MAX_MISC_ENTS)
{
return;
}
if (!MiscEnts)
{
MiscEnts = (refEntity_t *)trap_VM_LocalAlloc(sizeof(refEntity_t)*MAX_MISC_ENTS);
Radius = (float *)trap_VM_LocalAlloc(sizeof(float)*MAX_MISC_ENTS);
}
radius = &Radius[NumMiscEnts];
RefEnt = &MiscEnts[NumMiscEnts++];
modelIndex = trap_R_RegisterModel(data->mModel);
if (modelIndex == 0)
{
Com_Error(ERR_DROP, "client_model has invalid model definition");
return;
}
memset(RefEnt, 0, sizeof(refEntity_t));
RefEnt->reType = RT_MODEL;
RefEnt->hModel = modelIndex;
RefEnt->frame = 0;
trap_R_ModelBounds(modelIndex, mins, maxs);
VectorCopy(data->mScale, RefEnt->modelScale);
VectorCopy(data->mOrigin, RefEnt->origin);
VectorScaleVector(mins, data->mScale, mins);
VectorScaleVector(maxs, data->mScale, maxs);
*radius = Distance(mins, maxs);
AnglesToAxis( data->mAngles, RefEnt->axis );
CG_ScaleModelAxis(RefEnt);
}
void CG_DrawMiscEnts(void)
{
int i;
refEntity_t *RefEnt;
float *radius;
vec3_t difference;
RefEnt = MiscEnts;
radius = Radius;
for(i=0;i<NumMiscEnts;i++)
{
VectorSubtract(RefEnt->origin, cg.refdef.vieworg, difference);
if (VectorLength(difference)-(*radius) <= RMG_distancecull.value)
{
trap_R_AddRefEntityToScene(RefEnt);
}
RefEnt++;
radius++;
}
}

1119
code/cgame/cg_newDraw.c Normal file

File diff suppressed because it is too large Load Diff

119
code/cgame/cg_playeranim.c Normal file
View File

@ -0,0 +1,119 @@
#include "cg_local.h"
#include "animtable.h"
/*
======================
CG_ParseAnimationFile
Read a configuration file containing animation counts and rates
models/players/visor/animation.cfg, etc
======================
*/
qboolean CG_ParseAnimationFile ( const char *filename, clientInfo_t *ci)
{
const char *text_p;
int len;
int i;
char *token;
float fps;
int skip;
char text[20000];
fileHandle_t f;
int animNum;
animation_t *animations;
animations = ci->animations;
// load the file
len = trap_FS_FOpenFile( filename, &f, FS_READ );
if ( len <= 0 || len >= sizeof( text ) - 1 )
{
return qfalse;
}
trap_FS_Read( text, len, f );
text[len] = 0;
trap_FS_FCloseFile( f );
// parse the text
text_p = text;
skip = 0; // quiet the compiler warning
//FIXME: have some way of playing anims backwards... negative numFrames?
//initialize anim array so that from 0 to MAX_ANIMATIONS, set default values of 0 1 0 100
for(i = 0; i < MAX_ANIMATIONS; i++)
{
animations[i].firstFrame = 0;
animations[i].numFrames = 0;
animations[i].loopFrames = -1;
animations[i].frameLerp = 100;
animations[i].initialLerp = 100;
}
// read information for each frame
while(1)
{
token = COM_Parse( &text_p );
if ( !token || !token[0])
{
break;
}
animNum = GetIDForString(animTable, token);
if(animNum == -1)
{
//#ifndef FINAL_BUILD
#ifdef _DEBUG
Com_Printf(S_COLOR_RED"WARNING: Unknown token %s in %s\n", token, filename);
#endif
continue;
}
token = COM_Parse( &text_p );
if ( !token )
{
break;
}
animations[animNum].firstFrame = atoi( token );
token = COM_Parse( &text_p );
if ( !token )
{
break;
}
animations[animNum].numFrames = atoi( token );
token = COM_Parse( &text_p );
if ( !token )
{
break;
}
animations[animNum].loopFrames = atoi( token );
token = COM_Parse( &text_p );
if ( !token )
{
break;
}
fps = atof( token );
if ( fps == 0 )
{
fps = 1;//Don't allow divide by zero error
}
if ( fps < 0 )
{//backwards
animations[animNum].frameLerp = floor(1000.0f / fps);
}
else
{
animations[animNum].frameLerp = ceil(1000.0f / fps);
}
animations[animNum].initialLerp = ceil(1000.0f / fabs(fps));
}
return qtrue;
}

View File

1472
code/cgame/cg_players.c Normal file

File diff suppressed because it is too large Load Diff

313
code/cgame/cg_playerstate.c Normal file
View File

@ -0,0 +1,313 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_playerstate.c -- this file acts on changes in a new playerState_t
// With normal play, this will be done after local prediction, but when
// following another player or playing back a demo, it will be checked
// when the snapshot transitions like all the other entities
#include "cg_local.h"
/*
==============
CG_DamageFeedback
==============
*/
void CG_DamageFeedback( int yawByte, int pitchByte, int damage )
{
float kick;
int health;
float scale;
vec3_t dir;
vec3_t angles;
// show the attacking player's head and name in corner
cg.attackerTime = cg.time;
// the lower on health you are, the greater the view kick will be
health = cg.snap->ps.stats[STAT_HEALTH];
if ( health < 40 )
{
scale = 1;
}
else
{
scale = 40.0 / health;
}
kick = damage * scale;
if (kick < 5)
kick = 5;
if (kick > 10)
kick = 10;
// if yaw and pitch are both 255, make the damage always centered (falling, etc)
if ( yawByte == 255 && pitchByte == 255 )
{
cg.damageX = 0;
cg.damageY = 0;
cg.v_dmg_roll = 255;
cg.v_dmg_pitch = -kick;
}
else
{
float front;
float left;
angles[PITCH] = (float)pitchByte / 255.0f * 360.0f;
angles[YAW] = (float)yawByte / 255.0f * 360.0f;
angles[ROLL] = 0;
AngleVectors( angles, dir, NULL, NULL );
VectorSubtract( vec3_origin, dir, dir );
front = DotProduct (dir, cg.refdef.viewaxis[0] );
left = DotProduct (dir, cg.refdef.viewaxis[1] );
cg.v_dmg_roll = kick * left;
cg.v_dmg_pitch = -kick * front;
cg.damageY = -AngleNormalize180(angles[PITCH]);
cg.damageX = AngleNormalize180(angles[YAW] - cg.predictedPlayerState.viewangles[YAW] + 180);
}
// don't let the screen flashes vary as much
if ( kick > 10 )
{
kick = 10;
}
cg.damageTime = cg.snap->serverTime;
}
/*
================
CG_Respawn
A respawn happened this snapshot
================
*/
void CG_Respawn( void )
{
// no error decay on player movement
cg.thisFrameTeleport = qtrue;
// display weapons available
cg.weaponSelectTime = cg.time;
// select the weapon the server says we are using
cg.weaponSelect = cg.snap->ps.weapon;
// no more camera shake
cg.shakeStart = 0;
// Make sure the weapon selection menu isnt up
cg.weaponMenuUp = qfalse;
// clear any left over flash grenades
cg.flashbangTime = 0;
// Reset the animation
CG_SetWeaponAnim( cg.snap->ps.weaponAnimId&(~ANIM_TOGGLEBIT), &cg.snap->ps );
// Update the view weapon surfaces
CG_UpdateViewWeaponSurfaces ( &cg.snap->ps );
trap_ResetAutorun ( );
}
extern char *eventnames[];
/*
==============
CG_CheckPlayerstateEvents
==============
*/
void CG_CheckPlayerstateEvents( playerState_t *ps, playerState_t *ops )
{
int i;
int event;
centity_t *cent;
if ( ps->externalEvent && ps->externalEvent != ops->externalEvent )
{
cent = CG_GetEntity ( ps->clientNum );
cent->currentState.event = ps->externalEvent;
cent->currentState.eventParm = ps->externalEventParm;
CG_EntityEvent( cent, cent->lerpOrigin );
}
cent = &cg_entities[ ps->clientNum ];
// go through the predictable events buffer
for ( i = ps->eventSequence - MAX_PS_EVENTS ; i < ps->eventSequence ; i++ ) {
// if we have a new predictable event
if ( i >= ops->eventSequence
// or the server told us to play another event instead of a predicted event we already issued
// or something the server told us changed our prediction causing a different event
|| (i > ops->eventSequence - MAX_PS_EVENTS && ps->events[i & (MAX_PS_EVENTS-1)] != ops->events[i & (MAX_PS_EVENTS-1)]) ) {
event = ps->events[ i & (MAX_PS_EVENTS-1) ];
cent->currentState.event = event;
cent->currentState.eventParm = ps->eventParms[ i & (MAX_PS_EVENTS-1) ];
CG_EntityEvent( cent, cent->lerpOrigin );
cg.predictableEvents[ i & (MAX_PREDICTED_EVENTS-1) ] = event;
cg.eventSequence++;
}
}
}
/*
==================
CG_CheckChangedPredictableEvents
==================
*/
void CG_CheckChangedPredictableEvents( playerState_t *ps )
{
int i;
int event;
centity_t *cent;
cent = &cg_entities[ps->clientNum];
for ( i = ps->eventSequence - MAX_PS_EVENTS ; i < ps->eventSequence ; i++ )
{
//
if (i >= cg.eventSequence)
{
continue;
}
// if this event is not further back in than the maximum predictable events we remember
if (i > cg.eventSequence - MAX_PREDICTED_EVENTS)
{
// if the new playerstate event is different from a previously predicted one
if ( ps->events[i & (MAX_PS_EVENTS-1)] != cg.predictableEvents[i & (MAX_PREDICTED_EVENTS-1) ] )
{
event = ps->events[ i & (MAX_PS_EVENTS-1) ];
cent->currentState.event = event;
cent->currentState.eventParm = ps->eventParms[ i & (MAX_PS_EVENTS-1) ];
CG_EntityEvent( cent, cent->lerpOrigin );
cg.predictableEvents[ i & (MAX_PREDICTED_EVENTS-1) ] = event;
if ( cg_showmiss.integer )
{
Com_Printf("WARNING: changed predicted event\n");
}
}
}
}
}
/*
==================
CG_CheckLocalSounds
==================
*/
void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops )
{
// don't play the sounds if the player just changed teams
if ( ps->persistant[PERS_TEAM] != ops->persistant[PERS_TEAM] )
{
return;
}
// health changes of more than -1 should make pain sounds
if ( ps->stats[STAT_HEALTH] < ops->stats[STAT_HEALTH] - 1 )
{
if ( ps->stats[STAT_HEALTH] > 0 )
{
CG_PainEvent( &cg_entities[ps->clientNum], ps->stats[STAT_HEALTH] );
}
}
// Look for a zoom transition that isnt the first zoom in
if ( ops->zoomFov && (ps->zoomFov != ops->zoomFov) )
{
trap_S_StartLocalSound ( cgs.media.zoomSound, CHAN_AUTO );
}
}
/*
===============
CG_TransitionPlayerState
===============
*/
void CG_TransitionPlayerState( playerState_t *ps, playerState_t *ops )
{
// respawning. This is done before the follow mode check because spawn count is
// maintained into the following client
if ( ps->persistant[PERS_SPAWN_COUNT] != ops->persistant[PERS_SPAWN_COUNT] )
{
CG_Respawn();
}
// check for changing follow mode
if ( ps->clientNum != ops->clientNum )
{
cg.thisFrameTeleport = qtrue;
// make sure we don't get any unwanted transition effects
*ops = *ps;
}
// damage events (player is getting wounded)
if ( ps->damageEvent != ops->damageEvent && ps->damageCount )
{
CG_DamageFeedback( ps->damageYaw, ps->damagePitch, ps->damageCount );
}
// Make sure we clear the weapon menu when we die
if ( ps->stats[STAT_HEALTH] != ops->stats[STAT_HEALTH] )
{
if ( ps->stats[STAT_HEALTH] <= 0 )
{
cg.weaponMenuUp = qfalse;
cg.deathTime = cg.time;
trap_ResetAutorun ( );
}
}
if ( cg.mapRestart )
{
CG_Respawn();
cg.mapRestart = qfalse;
}
if ( cg.snap->ps.pm_type != PM_INTERMISSION && ps->persistant[PERS_TEAM] != TEAM_SPECTATOR )
{
CG_CheckLocalSounds( ps, ops );
}
// Always use the weapon from the player state when following
if( (ps->pm_flags & PMF_FOLLOW) || (ps->weapon != ops->weapon) )
{
cg.weaponSelect = ps->weapon;
}
// Check for weapon animation change.
if(ps->weaponAnimId!=ops->weaponAnimId )
{
CG_SetWeaponAnim(ps->weaponAnimId&(~ANIM_TOGGLEBIT),ps);
}
// run events
CG_CheckPlayerstateEvents( ps, ops );
// smooth the ducking viewheight change and not crouch jumping
if ( ps->viewheight != ops->viewheight && !(ps->pm_flags & PMF_CROUCH_JUMP) )
{
cg.duckChange = ps->viewheight - ops->viewheight;
cg.duckTime = cg.time;
}
// Need to update the view weapon surfaces when weapon states change
if ( ps->weaponstate != ops->weaponstate )
{
CG_UpdateViewWeaponSurfaces ( ps );
}
}

828
code/cgame/cg_predict.c Normal file
View File

@ -0,0 +1,828 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_predict.c -- this file generates cg.predictedPlayerState by either
// interpolating between snapshots from the server or locally predicting
// ahead the client's movement.
// It also handles local physics interaction, like fragments bouncing off walls
#include "cg_local.h"
static pmove_t cg_pmove;
static int cg_numSolidEntities;
static centity_t *cg_solidEntities[MAX_GENTITIES];
static int cg_numTriggerEntities;
static centity_t *cg_triggerEntities[MAX_ENTITIES_IN_SNAPSHOT];
/*
====================
CG_BuildSolidList
When a new cg.snap has been set, this function builds a sublist
of the entities that are actually solid, to make for more
efficient collision detection
====================
*/
void CG_BuildSolidList( void )
{
int i;
centity_t *cent;
snapshot_t *snap;
entityState_t *ent;
vec3_t difference;
float dsquared;
cg_numSolidEntities = 0;
cg_numTriggerEntities = 0;
if ( cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport )
{
snap = cg.nextSnap;
}
else
{
snap = cg.snap;
}
for ( i = 0 ; i < snap->numEntities ; i++ )
{
cent = CG_GetEntity ( snap->entities[ i ].number );
ent = &cent->currentState;
if ( ent->eType == ET_ITEM || ent->eType == ET_PUSH_TRIGGER || ent->eType == ET_TELEPORT_TRIGGER )
{
cg_triggerEntities[cg_numTriggerEntities] = cent;
cg_numTriggerEntities++;
continue;
}
if ( cent->nextState.solid )
{
cg_solidEntities[cg_numSolidEntities] = cent;
cg_numSolidEntities++;
continue;
}
}
dsquared = RMG_distancecull.value+500;
dsquared *= dsquared;
for(i=0;i<cg_numpermanents;i++)
{
cent = cg_permanents[i];
VectorSubtract(cent->lerpOrigin, snap->ps.origin, difference);
if (cent->currentState.eType == ET_TERRAIN ||
((difference[0]*difference[0]) + (difference[1]*difference[1]) + (difference[2]*difference[2])) <= dsquared)
{
cent->currentValid = qtrue;
if ( cent->nextState.solid )
{
cg_solidEntities[cg_numSolidEntities] = cent;
cg_numSolidEntities++;
}
}
else
{
cent->currentValid = qfalse;
}
}
}
/*
====================
CG_ClipMoveToEntities
====================
*/
static void CG_ClipMoveToEntities ( const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end,
int skipNumber, int mask, trace_t *tr ) {
int i, x, zd, zu;
trace_t trace;
entityState_t *ent;
clipHandle_t cmodel;
vec3_t bmins, bmaxs;
vec3_t origin, angles;
centity_t *cent;
for ( i = 0 ; i < cg_numSolidEntities ; i++ ) {
cent = cg_solidEntities[ i ];
ent = &cent->currentState;
if ( ent->number == skipNumber ) {
continue;
}
if ( ent->solid == SOLID_BMODEL ) {
// special value for bmodel
cmodel = trap_CM_InlineModel( ent->modelindex );
VectorCopy( cent->lerpAngles, angles );
BG_EvaluateTrajectory( &cent->currentState.pos, cg.physicsTime, origin );
} else {
// encoded bbox
x = (ent->solid & 255);
zd = ((ent->solid>>8) & 255);
zu = ((ent->solid>>16) & 255) - 32;
bmins[0] = bmins[1] = -x;
bmaxs[0] = bmaxs[1] = x;
bmins[2] = -zd;
bmaxs[2] = zu;
cmodel = trap_CM_TempBoxModel( bmins, bmaxs );
VectorCopy( vec3_origin, angles );
VectorCopy( cent->lerpOrigin, origin );
}
trap_CM_TransformedBoxTrace ( &trace, start, end,
mins, maxs, cmodel, mask, origin, angles);
if (trace.allsolid || trace.fraction < tr->fraction) {
trace.entityNum = ent->number;
*tr = trace;
} else if (trace.startsolid) {
tr->startsolid = qtrue;
}
if ( tr->allsolid ) {
return;
}
}
}
/*
================
CG_Trace
================
*/
void CG_Trace( trace_t *result, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int skipNumber, int mask )
{
trace_t t;
trap_CM_BoxTrace ( &t, start, end, mins, maxs, 0, mask);
t.entityNum = t.fraction != 1.0 ? ENTITYNUM_WORLD : ENTITYNUM_NONE;
// check all other solid models
CG_ClipMoveToEntities (start, mins, maxs, end, skipNumber, mask, &t);
*result = t;
}
/*
================
CG_PlayerTrace
Trace against all players in the game and return a precise ghoul location where they were hit
================
*/
void CG_PlayerTrace ( trace_t* tr, const vec3_t start, const vec3_t end, int skipNumber )
{
G2Trace_t G2Trace;
int i;
float hitlen;
int hit;
vec3_t hitloc;
hit = -1;
VectorSubtract ( end, start, hitloc );
hitlen = VectorLengthSquared ( hitloc );
for ( i = 0 ; i < cgs.maxclients ; i++ )
{
centity_t *cent;
animation_t *anim;
cent = &cg_entities[i];
// Look for reasons to not even bother with this client
if ( !cent->currentValid || cent->currentState.number == skipNumber || cent->currentState.eType != ET_PLAYER )
{
continue;
}
// Cant hit dead people
if ( cent->currentState.eFlags & EF_DEAD )
{
continue;
}
// Do a quick test to make sure its even close to the guy
if ( !Q_TestRaySphere ( cent->lerpOrigin, 50, start, end ) )
{
continue;
}
// See if the shot is even close to the player
G2Trace[0].mEntityNum = -1;
anim = &cg.hitAnimations[ cent->pe.legs.anim &(~ANIM_TOGGLEBIT) ];
trap_G2API_SetBoneAnim(cg.hitModel, 0, "model_root", anim->firstFrame, anim->firstFrame + anim->numFrames, BONE_ANIM_OVERRIDE_LOOP, 50.0f / anim->frameLerp, cent->pe.legs.animTime, -1, 0);
anim = &cg.hitAnimations[ cent->pe.torso.anim &(~ANIM_TOGGLEBIT)];
trap_G2API_SetBoneAnim(cg.hitModel, 0, "lower_lumbar", anim->firstFrame, anim->firstFrame + anim->numFrames, BONE_ANIM_OVERRIDE_LOOP, 50.0f / anim->frameLerp, cent->pe.torso.animTime, -1, 0);
trap_G2API_SetBoneAngles( cg.hitModel, 0, "upper_lumbar", cent->pe.ghoulUpperTorsoAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, cg.time );
trap_G2API_SetBoneAngles( cg.hitModel, 0, "lower_lumbar", cent->pe.ghoulLowerTorsoAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, cg.time );
trap_G2API_SetBoneAngles( cg.hitModel, 0, "cranium", cent->pe.ghoulHeadAngles, BONE_ANGLES_POSTMULT, POSITIVE_Z, NEGATIVE_Y, POSITIVE_X, 0,0, cg.time );
trap_G2API_CollisionDetect ( G2Trace, cg.hitModel, cent->pe.ghoulLegsAngles, cent->lerpOrigin, cg.time, cent->currentState.number, start, end, vec3_identity, 0, 2 );
if ( G2Trace[0].mEntityNum == i )
{
vec3_t temp;
float len;
VectorSubtract ( G2Trace[0].mCollisionPosition, start, temp );
len = VectorLengthSquared ( temp );
if ( len < hitlen )
{
hitlen = len;
hit = i;
VectorCopy ( G2Trace[0].mCollisionPosition, hitloc );
}
}
}
if ( hit != -1 )
{
tr->entityNum = hit;
VectorCopy ( hitloc, tr->endpos );
}
}
/*
================
CG_PointContents
================
*/
int CG_PointContents( const vec3_t point, int passEntityNum ) {
int i;
entityState_t *ent;
centity_t *cent;
clipHandle_t cmodel;
int contents;
contents = trap_CM_PointContents (point, 0);
for ( i = 0 ; i < cg_numSolidEntities ; i++ ) {
cent = cg_solidEntities[ i ];
ent = &cent->currentState;
if ( ent->number == passEntityNum ) {
continue;
}
if (ent->solid != SOLID_BMODEL) { // special value for bmodel
continue;
}
cmodel = trap_CM_InlineModel( ent->modelindex );
if ( !cmodel ) {
continue;
}
contents |= trap_CM_TransformedPointContents( point, cmodel, ent->origin, ent->angles );
}
return contents;
}
/*
========================
CG_InterpolatePlayerState
Generates cg.predictedPlayerState by interpolating between
cg.snap->player_state and cg.nextFrame->player_state
========================
*/
static void CG_InterpolatePlayerState( qboolean grabAngles ) {
float f;
int i;
playerState_t *out;
snapshot_t *prev, *next;
out = &cg.predictedPlayerState;
prev = cg.snap;
next = cg.nextSnap;
*out = cg.snap->ps;
// if we are still allowing local input, short circuit the view angles
if ( grabAngles )
{
usercmd_t cmd;
int cmdNum;
cmdNum = trap_GetCurrentCmdNumber();
trap_GetUserCmd( cmdNum, &cmd );
PM_UpdateViewAngles( out, &cmd );
}
// if the next frame is a teleport, we can't lerp to it
if ( cg.nextFrameTeleport ) {
return;
}
if ( !next )
{
return;
}
#ifndef _SNAPSHOT_EXTRAPOLATION
if ( next->serverTime <= prev->serverTime )
{
return;
}
#endif
f = (float)( cg.time - prev->serverTime ) / (float)( next->serverTime - prev->serverTime );
i = next->ps.bobCycle;
if ( i < prev->ps.bobCycle ) {
i += 256; // handle wraparound
}
out->bobCycle = prev->ps.bobCycle + f * ( i - prev->ps.bobCycle );
for ( i = 0 ; i < 3 ; i++ ) {
out->origin[i] = prev->ps.origin[i] + f * (next->ps.origin[i] - prev->ps.origin[i] );
if ( !grabAngles ) {
out->viewangles[i] = LerpAngle(
prev->ps.viewangles[i], next->ps.viewangles[i], f );
}
out->velocity[i] = prev->ps.velocity[i] +
f * (next->ps.velocity[i] - prev->ps.velocity[i] );
}
}
/*
===================
CG_TouchItem
===================
*/
static void CG_TouchItem( centity_t *cent )
{
gitem_t *item;
qboolean autoswitch = qfalse;
if ( !cg_predictItems.integer )
{
return;
}
if ( !BG_PlayerTouchesItem( &cg.predictedPlayerState, &cent->currentState, cg.time ) )
{
return;
}
// never pick an item up twice in a prediction
if ( cent->miscTime == cg.time )
{
return;
}
if ( !BG_CanItemBeGrabbed( cgs.gametype, &cent->currentState, &cg.predictedPlayerState ) )
{
// can't hold it
return;
}
item = &bg_itemlist[ cent->currentState.modelindex ];
// No item prediction on gametype items
if ( item->giType == IT_GAMETYPE || item->giType == IT_BACKPACK )
{
return;
}
// See if we should autoswitch
if ( bg_itemlist[cent->currentState.modelindex].giType == IT_WEAPON )
{
// Dont autoswitch if the weapon isnt a safe weapon
if ( cg_autoswitch.integer == 1 || weaponData[bg_itemlist[cent->currentState.modelindex].giTag].safe )
{
if ( !(cg.predictedPlayerState.stats[STAT_WEAPONS] & (1<<bg_itemlist[cent->currentState.modelindex].giTag)) )
{
autoswitch = qtrue;
}
}
}
// grab it
BG_AddPredictableEventToPlayerstate( EV_ITEM_PICKUP, cent->currentState.modelindex|(autoswitch?ITEM_AUTOSWITCHBIT:0) , &cg.predictedPlayerState);
// remove it from the frame so it won't be drawn
cent->currentState.eFlags |= EF_NODRAW;
// don't touch it again this prediction
cent->miscTime = cg.time;
// if its a weapon, give them some predicted ammo so the autoswitch will work
if ( item->giType == IT_WEAPON )
{
cg.predictedPlayerState.stats[ STAT_WEAPONS ] |= 1 << item->giTag;
if ( !cg.predictedPlayerState.ammo[ item->giTag ] )
{
cg.predictedPlayerState.ammo[ item->giTag ] = 1;
}
}
}
/*
=========================
CG_TouchTriggerPrediction
Predict push triggers and items
=========================
*/
static void CG_TouchTriggerPrediction( void ) {
int i;
trace_t trace;
entityState_t *ent;
clipHandle_t cmodel;
centity_t *cent;
qboolean spectator;
// dead clients don't activate triggers
if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) {
return;
}
spectator = ( cg.predictedPlayerState.pm_type == PM_SPECTATOR );
if ( cg.predictedPlayerState.pm_type != PM_NORMAL && !spectator ) {
return;
}
for ( i = 0 ; i < cg_numTriggerEntities ; i++ ) {
cent = cg_triggerEntities[ i ];
ent = &cent->currentState;
if ( ent->eType == ET_ITEM && !spectator ) {
CG_TouchItem( cent );
continue;
}
if ( ent->solid != SOLID_BMODEL ) {
continue;
}
cmodel = trap_CM_InlineModel( ent->modelindex );
if ( !cmodel ) {
continue;
}
trap_CM_BoxTrace( &trace, cg.predictedPlayerState.origin, cg.predictedPlayerState.origin,
cg_pmove.mins, cg_pmove.maxs, cmodel, -1 );
if ( !trace.startsolid ) {
continue;
}
if ( ent->eType == ET_TELEPORT_TRIGGER )
{
cg.hyperspace = qtrue;
}
}
}
/*
=================
CG_PredictPlayerState
Generates cg.predictedPlayerState for the current cg.time
cg.predictedPlayerState is guaranteed to be valid after exiting.
For demo playback, this will be an interpolation between two valid
playerState_t.
For normal gameplay, it will be the result of predicted usercmd_t on
top of the most recent playerState_t received from the server.
Each new snapshot will usually have one or more new usercmd over the last,
but we simulate all unacknowledged commands each time, not just the new ones.
This means that on an internet connection, quite a few pmoves may be issued
each frame.
OPTIMIZE: don't re-simulate unless the newly arrived snapshot playerState_t
differs from the predicted one. Would require saving all intermediate
playerState_t during prediction.
We detect prediction errors and allow them to be decayed off over several frames
to ease the jerk.
=================
*/
void CG_PredictPlayerState( void )
{
int cmdNum;
int current;
playerState_t oldPlayerState;
qboolean moved;
usercmd_t oldestCmd;
usercmd_t latestCmd;
// will be set if touching a trigger_teleport
cg.hyperspace = qfalse;
// if this is the first frame we must guarantee
// predictedPlayerState is valid even if there is some
// other error condition
if ( !cg.validPPS )
{
cg.validPPS = qtrue;
cg.predictedPlayerState = cg.snap->ps;
}
// demo playback just copies the moves
if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW) )
{
CG_InterpolatePlayerState( qfalse );
return;
}
// non-predicting local movement will grab the latest angles
if ( cg_nopredict.integer || cg_synchronousClients.integer )
{
CG_InterpolatePlayerState( qtrue );
return;
}
// prepare for pmove
#if _Debug
cg_pmove.isClient=-1;
#endif
cg_pmove.ps = &cg.predictedPlayerState;
cg_pmove.trace = CG_Trace;
cg_pmove.pointcontents = CG_PointContents;
if ( cg_pmove.ps->pm_type == PM_DEAD )
{
cg_pmove.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY;
}
else
{
cg_pmove.tracemask = MASK_PLAYERSOLID;
}
if ( cg.snap->ps.persistant[PERS_TEAM] == TEAM_SPECTATOR )
{
cg_pmove.tracemask &= ~CONTENTS_BODY; // spectators can fly through bodies
}
cg_pmove.noFootsteps = ( cgs.dmflags & DF_NO_FOOTSTEPS ) > 0;
// save the state before the pmove so we can detect transitions
oldPlayerState = cg.predictedPlayerState;
current = trap_GetCurrentCmdNumber();
// if we don't have the commands right after the snapshot, we
// can't accurately predict a current position, so just freeze at
// the last good position we had
cmdNum = current - CMD_BACKUP + 1;
trap_GetUserCmd( cmdNum, &oldestCmd );
if ( oldestCmd.serverTime > cg.snap->ps.commandTime && oldestCmd.serverTime < cg.time )
{
// special check for map_restart
if ( cg_showmiss.integer )
{
Com_Printf ("exceeded PACKET_BACKUP on commands\n");
}
return;
}
// get the latest command so we can know which commands are from previous map_restarts
trap_GetUserCmd( current, &latestCmd );
// get the most recent information we have, even if
// the server time is beyond our current cg.time,
// because predicted player positions are going to
// be ahead of everything else anyway
if ( cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport )
{
cg.predictedPlayerState = cg.nextSnap->ps;
cg.physicsTime = cg.nextSnap->serverTime;
}
else
{
cg.predictedPlayerState = cg.snap->ps;
cg.physicsTime = cg.snap->serverTime;
}
if ( pmove_msec.integer < 8 )
{
trap_Cvar_Set("pmove_msec", "8");
}
else if (pmove_msec.integer > 33)
{
trap_Cvar_Set("pmove_msec", "33");
}
cg_pmove.pmove_fixed = pmove_fixed.integer;// | cg_pmove_fixed.integer;
cg_pmove.pmove_msec = pmove_msec.integer;
// run cmds
moved = qfalse;
for ( cmdNum = current - CMD_BACKUP + 1 ; cmdNum <= current ; cmdNum++ )
{
// get the command
trap_GetUserCmd( cmdNum, &cg_pmove.cmd );
if ( cg_pmove.pmove_fixed )
{
PM_UpdateViewAngles( cg_pmove.ps, &cg_pmove.cmd );
}
// don't do anything if the time is before the snapshot player time
if ( cg_pmove.cmd.serverTime <= cg.predictedPlayerState.commandTime )
{
continue;
}
// don't do anything if the command was from a previous map_restart
if ( cg_pmove.cmd.serverTime > latestCmd.serverTime )
{
continue;
}
// check for a prediction error from last frame
// on a lan, this will often be the exact value
// from the snapshot, but on a wan we will have
// to predict several commands to get to the point
// we want to compare
if ( cg.predictedPlayerState.commandTime == oldPlayerState.commandTime )
{
vec3_t delta;
float len;
if ( cg.thisFrameTeleport )
{
// a teleport will not cause an error decay
VectorClear( cg.predictedError );
if ( cg_showmiss.integer )
{
Com_Printf( "PredictionTeleport\n" );
}
cg.thisFrameTeleport = qfalse;
}
else
{
vec3_t adjusted;
CG_AdjustPositionForMover( cg.predictedPlayerState.origin,
cg.predictedPlayerState.groundEntityNum, cg.physicsTime, cg.oldTime, adjusted );
if ( cg_showmiss.integer )
{
if (!VectorCompare( oldPlayerState.origin, adjusted ))
{
Com_Printf("prediction error\n");
}
}
VectorSubtract( oldPlayerState.origin, adjusted, delta );
len = VectorLength( delta );
if ( len > 0.1 )
{
if ( cg_showmiss.integer )
{
Com_Printf("Prediction miss: %f\n", len);
}
if ( cg_errorDecay.integer )
{
int t;
float f;
t = cg.time - cg.predictedErrorTime;
f = ( cg_errorDecay.value - t ) / cg_errorDecay.value;
if ( f < 0 )
{
f = 0;
}
if ( f > 0 && cg_showmiss.integer )
{
Com_Printf("Double prediction decay: %f\n", f);
}
VectorScale( cg.predictedError, f, cg.predictedError );
}
else
{
VectorClear( cg.predictedError );
}
VectorAdd( delta, cg.predictedError, cg.predictedError );
cg.predictedErrorTime = cg.oldTime;
}
}
}
// don't predict gauntlet firing, which is only supposed to happen
// when it actually inflicts damage
cg_pmove.gauntletHit = qfalse;
if ( cg_pmove.pmove_fixed )
{
cg_pmove.cmd.serverTime = ((cg_pmove.cmd.serverTime + pmove_msec.integer-1) / pmove_msec.integer) * pmove_msec.integer;
}
cg_pmove.animations = cgs.clientinfo[cg.clientNum].animations;
Pmove (&cg_pmove);
moved = qtrue;
// add push trigger movement effects
CG_TouchTriggerPrediction();
// check for predictable events that changed from previous predictions
//CG_CheckChangedPredictableEvents(&cg.predictedPlayerState);
}
if ( cg_showmiss.integer > 1 )
{
Com_Printf( "[%i : %i] ", cg_pmove.cmd.serverTime, cg.time );
}
if ( !moved )
{
if ( cg_showmiss.integer )
{
Com_Printf( "not moved\n" );
}
return;
}
// adjust for the movement of the groundentity
CG_AdjustPositionForMover( cg.predictedPlayerState.origin,
cg.predictedPlayerState.groundEntityNum,
cg.physicsTime, cg.time, cg.predictedPlayerState.origin );
if ( cg_showmiss.integer )
{
if (cg.predictedPlayerState.eventSequence > oldPlayerState.eventSequence + MAX_PS_EVENTS)
{
Com_Printf("WARNING: dropped event\n");
}
}
// fire events and other transition triggered things
CG_TransitionPlayerState( &cg.predictedPlayerState, &oldPlayerState );
if ( cg_showmiss.integer )
{
if (cg.eventSequence > cg.predictedPlayerState.eventSequence)
{
Com_Printf("WARNING: double event\n");
cg.eventSequence = cg.predictedPlayerState.eventSequence;
}
}
}
/*
===============
CG_InitHitModel
===============
*/
void CG_InitHitModel ( void )
{
void* ghoul2;
char temp[20480];
int numPairs;
qhandle_t handle;
ghoul2 = NULL;
// Initialize the ghoul2 model
trap_G2API_InitGhoul2Model ( &ghoul2,
"models/characters/average_sleeves/average_sleeves.glm",
0, 0, 0, (1<<4), 2 );
// Verify it
if ( !ghoul2 )
{
return;
}
// Parse the skin file that will be used for hit information
numPairs = BG_ParseSkin ( "models/characters/skins/col_rebel_h1.g2skin", temp, sizeof(temp) );
if ( !numPairs )
{
trap_G2API_CleanGhoul2Models ( &ghoul2 );
return;
}
// Register the skin and attach it to the ghoul model
handle = trap_G2API_RegisterSkin( "hitmodel", numPairs, temp );
trap_G2API_SetSkin( ghoul2, 0, handle );
// Read in the animations for this model
trap_G2API_GetAnimFileNameIndex( ghoul2, 0, temp );
BG_ParseAnimationFile ( va("%s_mp.cfg", temp), cg.hitAnimations );
// Hand the hit model back
cg.hitModel = ghoul2;
}

439
code/cgame/cg_public.h Normal file
View File

@ -0,0 +1,439 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_public.h --
/*
==================================================================
functions imported from the main executable
==================================================================
*/
#define CGAME_IMPORT_API_VERSION 4
typedef enum
{
CG_PRINT,
CG_ERROR,
CG_MILLISECONDS,
CG_CVAR_REGISTER,
CG_CVAR_UPDATE,
CG_CVAR_SET,
CG_CVAR_VARIABLESTRINGBUFFER,
CG_ARGC,
CG_ARGV,
CG_ARGS,
CG_FS_FOPENFILE,
CG_FS_READ,
CG_FS_WRITE,
CG_FS_FCLOSEFILE,
CG_FS_GETFILELIST,
CG_SENDCONSOLECOMMAND,
CG_ADDCOMMAND,
CG_SENDCLIENTCOMMAND,
CG_UPDATESCREEN,
CG_RMG_INIT,
CG_CM_LOADMAP,
CG_CM_NUMINLINEMODELS,
CG_CM_INLINEMODEL,
CG_CM_LOADMODEL,
CG_CM_TEMPBOXMODEL,
CG_CM_POINTCONTENTS,
CG_CM_TRANSFORMEDPOINTCONTENTS,
CG_CM_BOXTRACE,
CG_CM_TRANSFORMEDBOXTRACE,
CG_CM_MARKFRAGMENTS,
CG_S_STARTSOUND,
CG_S_STOPALLSOUNDS,
CG_S_STARTLOCALSOUND,
CG_S_CLEARLOOPINGSOUNDS,
CG_S_ADDLOOPINGSOUND,
CG_S_UPDATEENTITYPOSITION,
CG_S_RESPATIALIZE,
CG_S_REGISTERSOUND,
CG_S_STARTBACKGROUNDTRACK,
CG_AS_ADDPRECACHEENTRY,
CG_AS_PARSESETS,
CG_AS_UPDATEAMBIENTSET,
CG_AS_ADDLOCALSET,
CG_AS_GETBMODELSOUND,
CG_R_LOADWORLDMAP,
CG_R_REGISTERMODEL,
CG_R_REGISTERSKIN,
CG_R_REGISTERSHADER,
CG_R_CLEARSCENE,
CG_R_CLEARDECALS,
CG_R_ADDREFENTITYTOSCENE,
CG_R_ADDPOLYTOSCENE,
CG_R_ADDDECALTOSCENE,
CG_R_ADDLIGHTTOSCENE,
CG_R_RENDERSCENE,
CG_R_DRAWVISUALOVERLAY,
CG_R_SETCOLOR,
CG_R_DRAWSTRETCHPIC,
CG_R_MODELBOUNDS,
CG_R_LERPTAG,
CG_R_DRAWROTATEPIC,
CG_R_DRAWROTATEPIC2,
CG_R_DRAWTEXT,
CG_R_DRAWTEXTWITHCURSOR,
CG_R_GETTEXTWIDTH,
CG_R_GETTEXTHEIGHT,
CG_GETGLCONFIG,
CG_GETGAMESTATE,
CG_GETCURRENTSNAPSHOTNUMBER,
CG_GETSNAPSHOT,
CG_GETDEFAULTSTATE,
CG_GETSERVERCOMMAND,
CG_GETCURRENTCMDNUMBER,
CG_GETUSERCMD,
CG_SETUSERCMDVALUE,
CG_RW_SETTEAM,
CG_RESETAUTORUN,
CG_R_REGISTERSHADERNOMIP,
CG_MEMORY_REMAINING,
CG_R_REGISTERFONT,
CG_KEY_ISDOWN,
CG_KEY_GETCATCHER,
CG_KEY_SETCATCHER,
CG_KEY_GETKEY,
CG_PC_ADD_GLOBAL_DEFINE,
CG_PC_LOAD_SOURCE,
CG_PC_FREE_SOURCE,
CG_PC_READ_TOKEN,
CG_PC_SOURCE_FILE_AND_LINE,
CG_PC_LOAD_GLOBAL_DEFINES,
CG_PC_REMOVE_ALL_GLOBAL_DEFINES,
CG_MEMSET = 100,
CG_MEMCPY,
CG_STRNCPY,
CG_SIN,
CG_COS,
CG_ATAN2,
CG_SQRT,
CG_ANGLEVECTORS,
CG_PERPENDICULARVECTOR,
CG_FLOOR,
CG_CEIL,
CG_TESTPRINTINT,
CG_TESTPRINTFLOAT,
CG_ACOS,
CG_ASIN,
CG_MATRIXMULTIPLY,
CG_SP_GETSTRINGTEXTSTRING,
CG_S_STOPBACKGROUNDTRACK,
CG_REAL_TIME,
CG_SNAPVECTOR,
CG_REMOVECOMMAND,
CG_R_LIGHTFORPOINT,
CG_CIN_PLAYCINEMATIC,
CG_CIN_STOPCINEMATIC,
CG_CIN_RUNCINEMATIC,
CG_CIN_DRAWCINEMATIC,
CG_CIN_SETEXTENTS,
CG_R_REMAP_SHADER,
CG_R_GET_LIGHT_STYLE,
CG_R_SET_LIGHT_STYLE,
CG_FX_ADDLINE,
CG_S_ADDREALLOOPINGSOUND,
CG_S_STOPLOOPINGSOUND,
CG_CM_TEMPCAPSULEMODEL,
CG_CM_CAPSULETRACE,
CG_CM_TRANSFORMEDCAPSULETRACE,
CG_R_ADDADDITIVELIGHTTOSCENE,
CG_GET_ENTITY_TOKEN,
CG_R_ADDPOLYSTOSCENE,
CG_R_INPVS,
CG_FX_REGISTER_EFFECT,
CG_FX_PLAY_SIMPLE_EFFECT,
CG_FX_PLAY_EFFECT,
CG_FX_PLAY_ENTITY_EFFECT,
CG_FX_PLAY_SIMPLE_EFFECT_ID,
CG_FX_PLAY_EFFECT_ID,
CG_FX_PLAY_ENTITY_EFFECT_ID,
CG_FX_PLAY_BOLTED_EFFECT_ID,
CG_FX_ADD_SCHEDULED_EFFECTS,
CG_FX_INIT_SYSTEM,
CG_FX_FREE_SYSTEM,
CG_FX_ADJUST_TIME,
CG_FX_DRAW_2D_EFFECTS,
CG_FX_RESET,
CG_G2_LISTBONES,
CG_G2_LISTSURFACES,
CG_G2_ADDBOLT,
CG_G2_SETBOLTON,
CG_G2_REMOVEBOLT,
CG_G2_ATTACHG2MODEL,
CG_G2_DETACHG2MODEL,
CG_G2_HAVEWEGHOULMODELS,
CG_G2_SETMODELS,
CG_G2_GETBOLT,
CG_G2_INITGHOUL2MODEL,
CG_G2_CLEANMODELS,
CG_G2_ANGLEOVERRIDE,
CG_G2_PLAYANIM,
CG_G2_GETANIM,
CG_G2_SETSURFACEONOFF,
CG_G2_SETROOTSURFACE,
CG_G2_SETNEWORIGIN,
CG_G2_GETGLANAME,
CG_G2_COPYGHOUL2INSTANCE,
CG_G2_COPYSPECIFICGHOUL2MODEL,
CG_G2_DUPLICATEGHOUL2INSTANCE,
CG_G2_REMOVEGHOUL2MODEL,
CG_G2_ADDSKINGORE,
CG_G2_CLEARSKINGORE,
CG_G2_SETGHOUL2MODELFLAGS,
CG_G2_GETGHOUL2MODELFLAGS,
CG_G2_SETGHOUL2MODELFLAGSBYINDEX,
CG_G2_GETGHOUL2MODELFLAGSBYINDEX,
CG_G2_GETNUMMODELS,
CG_G2_GETANIMFILENAMEINDEX,
CG_G2_FINDBOLTINDEX,
CG_G2_GETBOLTINDEX,
CG_G2_REGISTERSKIN,
CG_G2_SETSKIN,
CG_G2_COLLISIONDETECT,
CG_MAT_RESET,
CG_MAT_CACHE,
CG_MAT_GET_SOUND,
CG_MAT_GET_DECAL,
CG_MAT_GET_DECAL_SCALE,
CG_MAT_GET_EFFECT,
CG_MAT_GET_DEBRIS,
CG_MAT_GET_DEBRIS_SCALE,
CG_CM_TM_CREATE,
CG_CM_TM_ADDBUILDING,
CG_CM_TM_ADDSPOT,
CG_CM_TM_ADDTARGET,
CG_CM_TM_UPLOAD,
CG_CM_TM_CONVERT_POS,
// CGenericParser2 (void *) routines
GP_PARSE,
GP_PARSE_FILE,
GP_CLEAN,
GP_DELETE,
GP_GET_BASE_PARSE_GROUP,
// CGPGroup (void *) routines
GPG_GET_NAME,
GPG_GET_NEXT,
GPG_GET_INORDER_NEXT,
GPG_GET_INORDER_PREVIOUS,
GPG_GET_PAIRS,
GPG_GET_INORDER_PAIRS,
GPG_GET_SUBGROUPS,
GPG_GET_INORDER_SUBGROUPS,
GPG_FIND_SUBGROUP,
GPG_FIND_PAIR,
GPG_FIND_PAIRVALUE,
// CGPValue (void *) routines
GPV_GET_NAME,
GPV_GET_NEXT,
GPV_GET_INORDER_NEXT,
GPV_GET_INORDER_PREVIOUS,
GPV_IS_LIST,
GPV_GET_TOP_VALUE,
GPV_GET_LIST,
CG_CM_REGISTER_TERRAIN,
CG_RE_INIT_RENDERER_TERRAIN,
CG_SET_SHARED_BUFFER,
CG_VM_LOCALALLOC,
CG_VM_LOCALALLOCUNALIGNED,
CG_VM_LOCALTEMPALLOC,
CG_VM_LOCALTEMPFREE,
CG_VM_LOCALSTRINGALLOC,
CG_UI_SETACTIVEMENU,
CG_UI_CLOSEALL,
} cgameImport_t;
/*
==================================================================
functions exported to the main executable
==================================================================
*/
typedef enum
{
CG_INIT,
// void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum )
// called when the level loads or when the renderer is restarted
// all media should be registered at this time
// cgame will display loading status by calling SCR_Update, which
// will call CG_DrawInformation during the loading process
// reliableCommandSequence will be 0 on fresh loads, but higher for
// demos, map restarts, or vid_restarts
CG_SHUTDOWN,
// void (*CG_Shutdown)( void );
// oportunity to flush and close any open files
CG_CONSOLE_COMMAND,
// qboolean (*CG_ConsoleCommand)( void );
// a console command has been issued locally that is not recognized by the
// main game system.
// use Cmd_Argc() / Cmd_Argv() to read the command, return qfalse if the
// command is not known to the game
CG_DRAW_ACTIVE_FRAME,
// void (*CG_DrawActiveFrame)( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback );
// Generates and draws a game scene and status information at the given time.
// If demoPlayback is set, local movement prediction will not be enabled
CG_CROSSHAIR_PLAYER,
// int (*CG_CrosshairPlayer)( void );
CG_LAST_ATTACKER,
// int (*CG_LastAttacker)( void );
CG_KEY_EVENT,
// void (*CG_KeyEvent)( int key, qboolean down );
CG_MOUSE_EVENT,
// void (*CG_MouseEvent)( int dx, int dy );
CG_EVENT_HANDLING,
// void (*CG_EventHandling)(int type);
CG_POINT_CONTENTS,
CG_GET_LERP_ORIGIN,
// void CG_LerpOrigin(int num, vec3_t result);
CG_GET_LERP_ANGLES,
CG_GET_MODEL_SCALE,
CG_GET_GHOUL2,
CG_GET_MODEL_LIST,
CG_CALC_LERP_POSITIONS,
// void CG_CalcEntityLerpPositions(int num);
CG_TRACE,
CG_GET_ORIGIN, // int entnum, vec3_t origin
CG_GET_ANGLES, // int entnum, vec3_t angle
CG_GET_ORIGIN_TRAJECTORY, // int entnum
CG_GET_ANGLE_TRAJECTORY, // int entnum
CG_FX_CAMERASHAKE,
CG_MISC_ENT,
CG_MAP_CHANGE,
} cgameExport_t;
// CG_POINT_CONTENTS
typedef struct
{
vec3_t mPoint; // input
int mPassEntityNum; // input
} TCGPointContents;
// CG_GET_LERP_ORIGIN
// CG_GET_LERP_ANGLES
// CG_GET_MODEL_SCALE
typedef struct
{
int mEntityNum; // input
vec3_t mPoint; // output
} TCGVectorData;
// CG_TRACE
typedef struct
{
trace_t mResult; // output
vec3_t mStart, mMins, mMaxs, mEnd; // input
int mSkipNumber, mMask; // input
} TCGTrace;
// CG_FX_CAMERASHAKE
typedef struct
{
vec3_t mOrigin; // input
float mIntensity; // input
int mRadius; // input
int mTime; // input
} TCGCameraShake;
// CG_MISC_ENT
typedef struct
{
char mModel[MAX_QPATH]; // input
vec3_t mOrigin, mAngles, mScale; // input
} TCGMiscEnt;
/// CG_CM_TM_CONVERT_POS
typedef struct
{
vec3_t mOrigin; // input
int mWidth, mHeight; // input
int mX, mY; // output
} TCGConvertPos;
#define MAX_CG_SHARED_BUFFER_SIZE 2048
#define CMD_BACKUP 64
#define CMD_MASK (CMD_BACKUP - 1)
// allow a lot of command backups for very fast systems
// multiple commands may be combined into a single packet, so this
// needs to be larger than PACKET_BACKUP
#define MAX_ENTITIES_IN_SNAPSHOT 256
// snapshots are a view of the server at a given time
// Snapshots are generated at regular time intervals by the server,
// but they may not be sent if a client's rate level is exceeded, or
// they may be dropped by the network.
typedef struct {
int snapFlags; // SNAPFLAG_RATE_DELAYED, etc
int ping;
int serverTime; // server time the message is valid for (in msec)
byte areamask[MAX_MAP_AREA_BYTES]; // portalarea visibility bits
playerState_t ps; // complete information about the current player at this time
int numEntities; // all of the entities that need to be presented
entityState_t entities[MAX_ENTITIES_IN_SNAPSHOT]; // at the time of this snapshot
int numServerCommands; // text based server commands to execute when this
int serverCommandSequence; // snapshot becomes current
} snapshot_t;
enum {
CGAME_EVENT_NONE,
CGAME_EVENT_TEAMMENU,
CGAME_EVENT_SCOREBOARD,
CGAME_EVENT_EDITHUD
};
//----------------------------------------------

521
code/cgame/cg_scoreboard.c Normal file
View File

@ -0,0 +1,521 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_scoreboard -- draw the scoreboard on top of the game screen
#include "cg_local.h"
#define SB_HEADER 86
#define SB_TOP (SB_HEADER+32)
// Where the status bar starts, so we don't overwrite it
#define SB_STATUSBAR 420
#define SB_MAXCLIENTS_NORMAL 12
#define SB_MAXCLIENTS_MORE 26
#define SB_MAXCLIENTS_ALOT 32
// Used when interleaved
#define SB_HEADER_WIDTH (580)
#define SB_HEADER_HEIGHT 30
#define SB_HEADER_X ((640-SB_HEADER_WIDTH)/2)
#define SB_HEADER_Y 86
#define SB_SCORELINE_X (SB_HEADER_X+30)
#define SB_SCORELINE_Y 120
#define SB_SCORELINE_WIDTH (SB_HEADER_WIDTH-60)
#define SB_NAME_X (SB_SCORELINE_X)
#define SB_SCORE_X (SB_SCORELINE_X+287)
#define SB_KILLS_X (SB_SCORELINE_X+335)
#define SB_DEATHS_X (SB_SCORELINE_X+384)
#define SB_PING_X (SB_SCORELINE_X+440)
#define SB_TIME_X (SB_SCORELINE_X+489)
int sb_lineHeight;
int sb_maxClients;
float sb_nameFontScale;
float sb_numberFontScale;
float sb_readyFontScale;
/*
=================
CG_DrawClientScore
=================
*/
static void CG_DrawClientScore( float x, float y, float w, score_t* score, float* color )
{
clientInfo_t* ci;
vec4_t dataColor;
vec4_t nameColor;
const char* s;
float f;
nameColor[3] = dataColor[3] = 1.0f;
// Validate the score
if ( score->client < 0 || score->client >= cgs.maxclients )
{
Com_Printf( "Bad score->client: %i\n", score->client );
return;
}
// Convienience
ci = &cgs.clientinfo[score->client];
CG_DrawPic ( x - 5, y, w, sb_lineHeight, cgs.media.scoreboardLine );
// highlight your position
if ( score->client == cg.snap->ps.clientNum )
{
vec4_t hcolor;
hcolor[0] = 1.0f;
hcolor[1] = 1.0f;
hcolor[2] = 1.0f;
hcolor[3] = .10f;
CG_FillRect( x - 5, y, w, sb_lineHeight, hcolor );
VectorSet ( nameColor, 1.0f, 1.0f, 1.0f );
VectorSet ( dataColor, 0.5f, 0.5f, 0.5f );
}
else if ( (cg.snap->ps.pm_type == PM_DEAD) && score->client == cg.snap->ps.persistant[PERS_ATTACKER] )
{
vec4_t hcolor;
hcolor[0] = 1.0f;
hcolor[1] = 1.0f;
hcolor[2] = 1.0f;
hcolor[3] = .10f;
CG_FillRect( x - 5, y, w, sb_lineHeight, hcolor );
VectorCopy ( color, nameColor );
VectorSet ( dataColor, 0.5f, 0.5f, 0.5f );
}
else
{
VectorCopy ( color, nameColor );
VectorSet ( dataColor, 0.3f, 0.3f, 0.3f );
if ( ci->ghost )
{
VectorScale ( nameColor, 0.6f, nameColor );
}
}
CG_DrawText( x, y, cgs.media.hudFont, sb_nameFontScale, nameColor, ci->name, 24, DT_OUTLINE );
s = va("%i", score->score );
f = trap_R_GetTextWidth ( s, cgs.media.hudFont, sb_nameFontScale, 0 );
CG_DrawText( x + w - 10 - f, y, cgs.media.hudFont, sb_nameFontScale, nameColor, va("%i", score->score), 0, DT_OUTLINE );
// Draw skull if dead and not in intermission
if ( cg.snap->ps.pm_type == PM_INTERMISSION )
{
if ( cg.snap->ps.stats[ STAT_CLIENTS_READY ] & ( 1 << score->client ) )
{
vec3_t deadColor;
deadColor[0] = 0.60f;
deadColor[1] = 0.60f;
deadColor[2] = 0.60f;
deadColor[3] = 1.0f;
CG_DrawText( x + w - 70, y + 3, cgs.media.hudFont, sb_readyFontScale, deadColor, "READY", 0, DT_OUTLINE );
}
}
else if ( ci->ghost )
{
CG_DrawPic ( x + w - 70, y + 1, sb_numberFontScale * 0.8f, sb_numberFontScale * 0.8f, cgs.media.deadShader );
}
// Draw any gametype items the guy is carrying
else
{
float xx = x + w - 70;
int i;
for ( i = 0; i < MAX_GAMETYPE_ITEMS; i ++ )
{
centity_t* cent;
cent = CG_GetEntity ( score->client);
// No have item, no draw it
if ( !(ci->gametypeitems & (1<<i) ) )
{
continue;
}
if ( !cg_items[MODELINDEX_GAMETYPE_ITEM+i].icon )
{
continue;
}
CG_DrawPic ( xx, y + 1, sb_numberFontScale * 0.8f, sb_numberFontScale * 0.8f, cg_items[MODELINDEX_GAMETYPE_ITEM+i].icon );
xx += sb_numberFontScale;
}
}
s = va("%i/%i", score->kills, score->deaths);
f = trap_R_GetTextWidth ( s, cgs.media.hudFont, sb_readyFontScale, 0 );
CG_DrawText( x + w - 10 - f, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, s, 0, 0 );
CG_DrawText( x, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, va("id: %i", score->client ), 0, 0 );
CG_DrawText( x + 40, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, va("ping: %i", score->ping ), 0, 0 );
CG_DrawText( x + 95, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, va("time: %i", score->time ), 0, 0 );
if ( score->teamkillDamage )
{
CG_DrawText( x + 150, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, va("tk: %i%%", score->teamkillDamage ), 0, 0 );
}
}
/*
=================
CG_TeamScoreboard
=================
*/
static int CG_TeamScoreboard( float x, float y, float w, team_t team )
{
int i;
int skipped;
float color[4];
int count;
clientInfo_t *ci;
const char* s;
int players;
qboolean drawnClient;
// Do we make sure the current client is drawn?
drawnClient = qtrue;
if ( cg.scores [ cg.snap->ps.clientNum ].team == team )
{
drawnClient = qfalse;
}
// Determine the color for this team
switch ( team )
{
case TEAM_RED:
VectorCopy4 ( g_color_table[ColorIndex(COLOR_RED)], color );
break;
case TEAM_BLUE:
VectorCopy4 ( g_color_table[ColorIndex(COLOR_BLUE)], color );
break;
case TEAM_FREE:
VectorCopy4 ( g_color_table[ColorIndex(COLOR_GREEN)], color );
break;
case TEAM_SPECTATOR:
default:
VectorCopy4 ( colorWhite, color );
break;
}
// Draw as many clients as we can for this team
for ( skipped = -1, count = 0, i = 0 ; i < cg.numScores && count < sb_maxClients ; i++ )
{
score_t* score;
score = &cg.scores[i];
ci = &cgs.clientinfo[ score->client ];
if ( team != score->team )
{
continue;
}
if ( count == sb_maxClients - 1 && !drawnClient )
{
if ( score->client != cg.snap->ps.clientNum )
{
skipped = i;
continue;
}
drawnClient = qtrue;
}
CG_DrawClientScore( x, y + SB_HEADER_HEIGHT + sb_lineHeight * count, w, score, color );
count++;
}
if ( skipped != -1 && count < sb_maxClients )
{
CG_DrawClientScore( x, y + SB_HEADER_HEIGHT + sb_lineHeight * count, w, &cg.scores[skipped], color );
count++;
}
s = "";
switch ( team )
{
case TEAM_RED:
s = "RED TEAM";
players = ui_info_redcount.integer;
break;
case TEAM_BLUE:
s = "BLUE TEAM";
players = ui_info_bluecount.integer;
break;
case TEAM_FREE:
s = "PLAYERS";
players = ui_info_freecount.integer;
break;
default:
case TEAM_SPECTATOR:
s = "SPECTATORS";
players = ui_info_speccount.integer;
break;
}
// Use the same team color here, but alpha it a bit.
color[3] = 0.6f;
// Draw the header information for this team
CG_DrawPic ( x - 5, y, w, 25, cgs.media.scoreboardHeader );
CG_FillRect( x - 5, y, w, 25, color );
CG_DrawText ( x, y, cgs.media.hudFont, 0.40f, colorWhite, va("%s", s), 0, 0 );
CG_DrawText ( x, y + 13, cgs.media.hudFont, 0.30f, colorWhite, va("players: %d", players), 0, 0 );
// Draw the totals if this is the red or blue team
if ( (team == TEAM_RED || team == TEAM_BLUE))
{
const char* s;
float f;
s = va("%d",(cg.teamScores[team-TEAM_RED]));
f = trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.43f, 0 );
CG_DrawText ( x + w - 10 - f, y, cgs.media.hudFont, 0.43f, colorWhite, s, 0, DT_OUTLINE );
}
if ( count )
{
CG_DrawPic ( x - 5, y + SB_HEADER_HEIGHT + sb_lineHeight * count, w, sb_lineHeight, cgs.media.scoreboardFooter );
}
y = count * sb_lineHeight + y + 10;
if ( y > cg.scoreBoardBottom )
{
cg.scoreBoardBottom = y;
}
return y;
}
/*
=================
CG_DrawNormalScoreboard
Draws a scoreboard that has no teams
=================
*/
qboolean CG_DrawNormalScoreboard ( float y )
{
cg.scoreBoardBottom = 0;
// DRaw the game timer and the game type
CG_DrawText ( 385, y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, "Game Time:", 0, DT_OUTLINE );
CG_DrawTimer ( 455, y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, DT_OUTLINE, cg.time - cgs.levelStartTime );
CG_DrawText ( 150, y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, cgs.gametypeData->displayName, 0, DT_OUTLINE );
if ( ui_info_speccount.integer )
{
CG_FillRect ( 0, 470, 640, 10, colorBlack );
CG_DrawText ( 5, 470, cgs.media.hudFont, 0.30f, colorWhite, va("SPECTATORS: %s", cg.scoreBoardSpectators), 0, 0 );
}
if ( ui_info_freecount.integer > 10 )
{
sb_maxClients = 16;
sb_lineHeight = 20;
sb_nameFontScale = 0.35f;
sb_readyFontScale = 0.30f;
sb_numberFontScale = trap_R_GetTextHeight ( "W", cgs.media.hudFont, sb_nameFontScale, 0 );
}
else
{
sb_maxClients = 10;
sb_lineHeight = 30;
sb_nameFontScale = 0.43f;
sb_readyFontScale = 0.30f;
sb_numberFontScale = trap_R_GetTextHeight ( "W", cgs.media.hudFont, sb_nameFontScale, 0 ) + 4;
}
CG_TeamScoreboard ( 150, y, 350, TEAM_FREE );
return qtrue;
}
/*
=================
CG_DrawTeamScoreboard
Draw the normal in-game scoreboard
=================
*/
qboolean CG_DrawTeamScoreboard( float y )
{
qboolean redFirst = qfalse;
cg.scoreBoardBottom = 0;
// DRaw the game timer and the game type
CG_DrawText ( 470, y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, "Game Time:", 0, DT_OUTLINE );
CG_DrawTimer ( 540, y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, DT_OUTLINE, cg.time - cgs.levelStartTime );
CG_DrawText ( 60, y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, cgs.gametypeData->displayName, 0, DT_OUTLINE );
if ( ui_info_speccount.integer )
{
CG_FillRect ( 0, 470, 640, 10, colorBlack );
CG_DrawText ( 5, 470, cgs.media.hudFont, 0.30f, colorWhite, va("SPECTATORS: %s", cg.scoreBoardSpectators), 0, 0 );
}
if ( ui_info_redcount.integer > 10 || ui_info_bluecount.integer > 10 )
{
sb_maxClients = 16;
sb_lineHeight = 20;
sb_nameFontScale = 0.35f;
sb_readyFontScale = 0.30f;
sb_numberFontScale = trap_R_GetTextHeight ( "W", cgs.media.hudFont, sb_nameFontScale, 0 );
}
else
{
sb_maxClients = 10;
sb_lineHeight = 30;
sb_nameFontScale = 0.43f;
sb_readyFontScale = 0.30f;
sb_numberFontScale = trap_R_GetTextHeight ( "W", cgs.media.hudFont, sb_nameFontScale, 0 ) + 4;
}
// If there are more scores than the scoreboard can show then show the
// players team first rather than the winning team
if ( cgs.clientinfo[cg.clientNum].team == TEAM_SPECTATOR )
{
if ( cg.teamScores[0] >= cg.teamScores[1] )
{
redFirst = qtrue;
}
}
else if ( cgs.clientinfo[cg.clientNum].team == TEAM_RED )
{
redFirst = qtrue;
}
if ( redFirst )
{
CG_TeamScoreboard( 50, y, 265, TEAM_RED );
CG_TeamScoreboard( 330, y, 265, TEAM_BLUE );
}
else
{
CG_TeamScoreboard( 330, y, 265, TEAM_RED );
CG_TeamScoreboard( 50, y, 265, TEAM_BLUE );
}
return qtrue;
}
/*
=================
CG_DrawScoreboard
Draws either a team or a normal scoreboard
=================
*/
qboolean CG_DrawScoreboard ( void )
{
float y;
float w;
// don't draw amuthing if the menu or console is up
if ( cg_paused.integer )
{
cg.deferredPlayerLoading = 0;
return qfalse;
}
// don't draw scoreboard during death while warmup up
if ( cg.warmup && !cg.showScores )
{
return qfalse;
}
if ( !cg.showScores &&
cg.predictedPlayerState.pm_type != PM_DEAD &&
cg.predictedPlayerState.pm_type != PM_INTERMISSION )
{
return qfalse;
}
// scoreboard
y = 45;
if ( cgs.gametypeData->teams )
{
if ( ui_info_redcount.integer < 10 && ui_info_bluecount.integer < 10 )
{
y += 50;
}
}
else if ( ui_info_freecount.integer < 10 )
{
y += 50;
}
// Draw any gameover text
if ( cgs.gameover[0] )
{
w = trap_R_GetTextWidth ( cgs.gameover, cgs.media.hudFont, 0.48f, 0 );
CG_DrawText ( 320 - w / 2, y - 30, cgs.media.hudFont, 0.48f, colorWhite, cgs.gameover, 0, DT_OUTLINE );
}
else if ( cgs.gametypeMessageTime > cg.time )
{
w = trap_R_GetTextWidth ( cgs.gametypeMessage, cgs.media.hudFont, 0.48f, 0 );
CG_DrawText ( 320 - w / 2, y - 30, cgs.media.hudFont, 0.48f, colorWhite, cgs.gametypeMessage, 0, DT_OUTLINE );
}
// Should we draw who killed you?
else if ( cg.snap->ps.pm_type == PM_DEAD &&
cg.snap->ps.persistant[PERS_ATTACKER] < MAX_CLIENTS &&
cg.snap->ps.persistant[PERS_ATTACKER] != cg.snap->ps.clientNum )
{
const char* s;
s = va("Killed by %s", cgs.clientinfo[cg.snap->ps.persistant[PERS_ATTACKER]].name );
w = trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.48f, 0 );
CG_DrawText ( 320 - w / 2, y - 30, cgs.media.hudFont, 0.48f, colorWhite, s, 0, DT_OUTLINE );
}
else if ( cgs.gametypeData->teams )
{
const char* s;
if ( cg.teamScores[0] == cg.teamScores[1] )
{
s = va ( "Game Tied at %d", cg.teamScores[0] );
}
else if ( cg.teamScores[0] > cg.teamScores[1] )
{
s = va ( "Red leads Blue by %d", cg.teamScores[0] - cg.teamScores[1] );
}
else
{
s = va ( "Blue leads Red by %d", cg.teamScores[1] - cg.teamScores[0] );
}
w = trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.48f, 0 );
CG_DrawText ( 320 - w / 2, y - 30, cgs.media.hudFont, 0.48f, colorWhite, s, 0, DT_OUTLINE );
}
// load any models that have been deferred
cg.deferredPlayerLoading++;
if ( cgs.gametypeData->teams )
{
return CG_DrawTeamScoreboard ( y );
}
return CG_DrawNormalScoreboard ( y );
}

1052
code/cgame/cg_servercmds.c Normal file

File diff suppressed because it is too large Load Diff

503
code/cgame/cg_snapshot.c Normal file
View File

@ -0,0 +1,503 @@
// Copyright (C) 2001-2002 Raven Software.
//
// cg_snapshot.c -- things that happen on snapshot transition,
// not necessarily every single rendered frame
#include "cg_local.h"
/*
==================
CG_ResetEntity
==================
*/
static void CG_ResetEntity( centity_t *cent )
{
// if the previous snapshot this entity was updated in is at least
// an event window back in time then we can reset the previous event
if ( cent->snapShotTime < cg.time - EVENT_VALID_MSEC )
{
cent->previousEvent = 0;
}
cent->trailTime = cg.snap->serverTime;
VectorCopy (cent->currentState.origin, cent->lerpOrigin);
VectorCopy (cent->currentState.angles, cent->lerpAngles);
if ( cent->currentState.eType == ET_PLAYER )
{
CG_ResetPlayerEntity( cent );
}
cent->pe.weapon = 0;
}
/*
===============
CG_TransitionEntity
cent->nextState is moved to cent->currentState and events are fired
===============
*/
static void CG_TransitionEntity( centity_t *cent )
{
cent->currentState = cent->nextState;
cent->currentValid = qtrue;
// reset if the entity wasn't in the last frame or was teleported
if ( !cent->interpolate ) {
CG_ResetEntity( cent );
}
// Time is overloaded for players to store the spawn count, so when a player is newly spawned
// their gore should be reset
if ( cent->pe.spawnCount != cent->currentState.time )
{
cent->pe.spawnCount = cent->currentState.time;
// Force all the animations to be restarted
cent->pe.torso.anim = -1;
cent->pe.legs.anim = -1;
if ( cent->ghoul2 )
{
trap_G2API_ClearSkinGore ( cent->ghoul2 );
}
}
// clear the next state. if will be set by the next CG_SetNextSnap
cent->interpolate = qfalse;
// check for events
CG_CheckEvents( cent );
}
/*
==================
CG_SetInitialSnapshot
This will only happen on the very first snapshot, or
on map restarts. All other times will use
CG_TransitionSnapshot instead.
FIXME: Also called by map_restart?
==================
*/
void CG_SetInitialSnapshot( snapshot_t *snap )
{
int i;
centity_t *cent;
entityState_t *state;
cg.snap = snap;
cent = CG_GetEntity ( snap->ps.clientNum );
if (!cgs.clientinfo[snap->ps.clientNum].ghoul2Model)
{
Com_Error(ERR_DROP, "CG_SetInitialSnapshot invalid g2 pointer for client\n");
}
if ((cent->ghoul2 == NULL) && trap_G2_HaveWeGhoul2Models(cgs.clientinfo[snap->ps.clientNum].ghoul2Model))
{
trap_G2API_DuplicateGhoul2Instance(cgs.clientinfo[snap->ps.clientNum].ghoul2Model, &cent->ghoul2);
}
BG_PlayerStateToEntityState( &snap->ps, &cent->currentState, qfalse );
// sort out solid entities
CG_BuildSolidList();
CG_ExecuteNewServerCommands( snap->serverCommandSequence );
// set our local weapon selection pointer to
// what the server has indicated the current weapon is
CG_Respawn();
for ( i = 0 ; i < cg.snap->numEntities ; i++ )
{
state = &cg.snap->entities[ i ];
cent = CG_GetEntity ( state->number );
memcpy(&cent->currentState, state, sizeof(entityState_t));
//cent->currentState = *state;
cent->interpolate = qfalse;
cent->currentValid = qtrue;
CG_ResetEntity( cent );
// check for events
CG_CheckEvents( cent );
}
}
/*
===================
CG_TransitionSnapshot
The transition point from snap to nextSnap has passed
===================
*/
static void CG_TransitionSnapshot( void )
{
centity_t *cent;
snapshot_t *oldFrame;
int i;
if ( !cg.snap )
{
Com_Error( ERR_FATAL, "CG_TransitionSnapshot: NULL cg.snap" );
}
if ( !cg.nextSnap )
{
Com_Error( ERR_FATAL, "CG_TransitionSnapshot: NULL cg.nextSnap" );
}
// execute any server string commands before transitioning entities
CG_ExecuteNewServerCommands( cg.nextSnap->serverCommandSequence );
// if we had a map_restart, set everthing with initial
if ( !cg.snap )
{
}
// clear the currentValid flag for all entities in the existing snapshot
for ( i = 0 ; i < cg.snap->numEntities ; i++ )
{
cent = CG_GetEntity ( cg.snap->entities[ i ].number );
cent->currentValid = qfalse;
}
// move nextSnap to snap and do the transitions
oldFrame = cg.snap;
cg.snap = cg.nextSnap;
cent = CG_GetEntity ( cg.snap->ps.clientNum );
BG_PlayerStateToEntityState( &cg.snap->ps, &cent->currentState, qfalse );
cent->interpolate = qfalse;
cent->currentValid = qtrue;
for ( i = 0 ; i < cg.snap->numEntities ; i++ )
{
// Transition the entity
cent = CG_GetEntity ( cg.snap->entities[ i ].number );
CG_TransitionEntity( cent );
// remember time of snapshot this entity was last updated in
cent->snapShotTime = cg.snap->serverTime;
}
cg.nextSnap = NULL;
// check for playerstate transition events
if ( oldFrame )
{
playerState_t *ops, *ps;
ops = &oldFrame->ps;
ps = &cg.snap->ps;
// teleporting checks are irrespective of prediction
if ( ( ps->eFlags ^ ops->eFlags ) & EF_TELEPORT_BIT )
{
cg.thisFrameTeleport = qtrue; // will be cleared by prediction code
}
// if we are not doing client side movement prediction for any
// reason, then the client events and view changes will be issued now
if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW)
|| cg_nopredict.integer || cg_synchronousClients.integer )
{
CG_TransitionPlayerState( ps, ops );
}
}
}
/*
===================
CG_SetNextSnap
A new snapshot has just been read in from the client system.
===================
*/
static void CG_SetNextSnap( snapshot_t *snap )
{
int num;
entityState_t *es;
centity_t *cent;
cg.nextSnap = snap;
cent = CG_GetEntity ( snap->ps.clientNum );
BG_PlayerStateToEntityState( &snap->ps, &cent->nextState, qfalse );
cent->interpolate = qtrue;
// check for extrapolation errors
for ( num = 0 ; num < snap->numEntities ; num++ )
{
es = &snap->entities[num];
cent = CG_GetEntity ( es->number );
memcpy(&cent->nextState, es, sizeof(entityState_t));
//cent->nextState = *es;
// if this frame is a teleport, or the entity wasn't in the
// previous frame, don't interpolate
if ( !cent->currentValid || ( ( cent->currentState.eFlags ^ es->eFlags ) & EF_TELEPORT_BIT ) )
{
cent->interpolate = qfalse;
}
else
{
cent->interpolate = qtrue;
}
}
// if the next frame is a teleport for the playerstate, we
// can't interpolate during demos
if ( cg.snap && ( ( snap->ps.eFlags ^ cg.snap->ps.eFlags ) & EF_TELEPORT_BIT ) )
{
cg.nextFrameTeleport = qtrue;
}
else
{
cg.nextFrameTeleport = qfalse;
}
// if changing follow mode, don't interpolate
if ( cg.nextSnap->ps.clientNum != cg.snap->ps.clientNum )
{
cg.nextFrameTeleport = qtrue;
}
// if changing server restarts, don't interpolate
if ( ( cg.nextSnap->snapFlags ^ cg.snap->snapFlags ) & SNAPFLAG_SERVERCOUNT )
{
cg.nextFrameTeleport = qtrue;
}
// sort out solid entities
CG_BuildSolidList();
}
/*
========================
CG_ReadNextSnapshot
This is the only place new snapshots are requested
This may increment cgs.processedSnapshotNum multiple
times if the client system fails to return a
valid snapshot.
========================
*/
static snapshot_t *CG_ReadNextSnapshot( void ) {
qboolean r;
snapshot_t *dest;
if ( cg.latestSnapshotNum > cgs.processedSnapshotNum + 1000 ) {
Com_Printf( "WARNING: CG_ReadNextSnapshot: way out of range, %i > %i",
cg.latestSnapshotNum, cgs.processedSnapshotNum );
}
while ( cgs.processedSnapshotNum < cg.latestSnapshotNum ) {
/*
// decide which of the two slots to load it into
if ( cg.snap == &cg.activeSnapshots[0] ) {
dest = &cg.activeSnapshots[1];
} else {
dest = &cg.activeSnapshots[0];
}
*/
dest = &cg.activeSnapshots[cg.activeSnapshot%3];
// try to read the snapshot from the client system
cgs.processedSnapshotNum++;
r = trap_GetSnapshot( cgs.processedSnapshotNum, dest );
// FIXME: why would trap_GetSnapshot return a snapshot with the same server time
if ( cg.nextSnap && r && dest->serverTime == cg.nextSnap->serverTime ) {
// r = r;
// continue;
}
// if it succeeded, return
if ( r ) {
cg.activeSnapshot++;
CG_AddLagometerSnapshotInfo( dest );
return dest;
}
// a GetSnapshot will return failure if the snapshot
// never arrived, or is so old that its entities
// have been shoved off the end of the circular
// buffer in the client system.
// record as a dropped packet
CG_AddLagometerSnapshotInfo( NULL );
// If there are additional snapshots, continue trying to
// read them.
}
// nothing left to read
return NULL;
}
/*
============
CG_ProcessSnapshots
We are trying to set up a renderable view, so determine
what the simulated time is, and try to get snapshots
both before and after that time if available.
If we don't have a valid cg.snap after exiting this function,
then a 3D game view cannot be rendered. This should only happen
right after the initial connection. After cg.snap has been valid
once, it will never turn invalid.
Even if cg.snap is valid, cg.nextSnap may not be, if the snapshot
hasn't arrived yet (it becomes an extrapolating situation instead
of an interpolating one)
============
*/
void CG_ProcessSnapshots( void )
{
snapshot_t *snap;
int n;
// see what the latest snapshot the client system has is
trap_GetCurrentSnapshotNumber( &n, &cg.latestSnapshotTime );
if ( n != cg.latestSnapshotNum )
{
if ( n < cg.latestSnapshotNum )
{
// this should never happen
Com_Error( ERR_FATAL, "CG_ProcessSnapshots: n < cg.latestSnapshotNum" );
}
cg.latestSnapshotNum = n;
}
// If we have yet to receive a snapshot, check for it.
// Once we have gotten the first snapshot, cg.snap will
// always have valid data for the rest of the game
while ( !cg.snap )
{
snap = CG_ReadNextSnapshot();
if ( !snap )
{
// we can't continue until we get a snapshot
return;
}
// set our weapon selection to what
// the playerstate is currently using
if ( !( snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) )
{
CG_SetInitialSnapshot( snap );
}
}
// loop until we either have a valid nextSnap with a serverTime
// greater than cg.time to interpolate towards, or we run
// out of available snapshots
do
{
// if we don't have a nextframe, try and read a new one in
if ( !cg.nextSnap || cg.needNextSnap ) // !cg.nextSnap )
{
snap = CG_ReadNextSnapshot();
// if we still don't have a nextframe, we will just have to
// extrapolate
if ( !snap )
{
if ( cg_drawSnapshot.integer )
Com_Printf ( "NOSNAP\n" );
break;
}
#ifdef _SNAPSHOT_EXTRAPOLATION
cg.needNextSnap = qfalse;
if ( cg.nextSnap)
{
if ( cg_drawSnapshot.integer )
Com_Printf ( "TRANS\n" );
CG_TransitionSnapshot();
}
#endif
CG_SetNextSnap( snap );
// if time went backwards, we have a level restart
if ( cg.nextSnap->serverTime < cg.snap->serverTime )
{
Com_Error( ERR_FATAL, "CG_ProcessSnapshots: Server time went backwards" );
}
}
#ifdef _SNAPSHOT_EXTRAPOLATION
if ( cg.needNextSnap )
{
if ( cg_drawSnapshot.integer )
Com_Printf ( "NEED\n" );
break;
}
#endif
// if our time is < nextFrame's, we have a nice interpolating state
if ( cg.time >= cg.snap->serverTime && cg.time < cg.nextSnap->serverTime )
{
break;
}
#ifdef _SNAPSHOT_EXTRAPOLATION
cg.needNextSnap = qtrue;
if ( cg_drawSnapshot.integer )
Com_Printf ( "SNAP: time=%i\n", cg.time );
#else
// we have passed the transition from nextFrame to frame
CG_TransitionSnapshot();
#endif
} while ( 1 );
// assert our valid conditions upon exiting
if ( cg.snap == NULL )
{
Com_Error( ERR_FATAL, "CG_ProcessSnapshots: cg.snap == NULL" );
}
if ( cg.time < cg.snap->serverTime )
{
// this can happen right after a vid_restart
cg.time = cg.snap->serverTime;
}
#ifndef _SNAPSHOT_EXTRAPOLATION
if ( cg.nextSnap != NULL && cg.nextSnap->serverTime <= cg.time )
{
Com_Error( ERR_FATAL, "CG_ProcessSnapshots: cg.nextSnap->serverTime <= cg.time" );
}
#endif
}

229
code/cgame/cg_syscalls.asm Normal file
View File

@ -0,0 +1,229 @@
code
equ trap_Print -1 ; CG_PRINT
equ trap_Error -2 ; CG_ERROR
equ trap_Milliseconds -3 ; CG_MILLISECONDS
equ trap_Cvar_Register -4 ; CG_CVAR_REGISTER
equ trap_Cvar_Update -5 ; CG_CVAR_UPDATE
equ trap_Cvar_Set -6 ; CG_CVAR_SET
equ trap_Cvar_VariableStringBuffer -7 ; CG_CVAR_VARIABLESTRINGBUFFER
equ trap_Argc -8 ; CG_ARGC
equ trap_Argv -9 ; CG_ARGV
equ trap_Args -10 ; CG_ARGS
equ trap_FS_FOpenFile -11 ; CG_FS_FOPENFILE
equ trap_FS_Read -12 ; CG_FS_READ
equ trap_FS_Write -13 ; CG_FS_WRITE
equ trap_FS_FCloseFile -14 ; CG_FS_FCLOSEFILE
equ trap_SendConsoleCommand -16 ; CG_SENDCONSOLECOMMAND
equ trap_AddCommand -17 ; CG_ADDCOMMAND
equ trap_RemoveCommand -121 ; CG_REMOVECOMMAND
equ trap_SendClientCommand -18 ; CG_SENDCLIENTCOMMAND
equ trap_UpdateScreen -19 ; CG_UPDATESCREEN
equ trap_RMG_Init -20 ; CG_RMG_INIT
equ trap_CM_LoadMap -21 ; CG_CM_LOADMAP
equ trap_CM_NumInlineModels -22 ; CG_CM_NUMINLINEMODELS
equ trap_CM_InlineModel -23 ; CG_CM_INLINEMODEL
equ trap_CM_TempBoxModel -25 ; CG_CM_TEMPBOXMODEL
equ trap_CM_TempCapsuleModel -134 ; CG_CM_TEMPCAPSULEMODEL
equ trap_CM_PointContents -26 ; CG_CM_POINTCONTENTS
equ trap_CM_TransformedPointContents -27 ; CG_CM_TRANSFORMEDPOINTCONTENTS
equ trap_CM_BoxTrace -28 ; CG_CM_BOXTRACE
equ trap_CM_CapsuleTrace -135 ; CG_CM_CAPSULETRACE
equ trap_CM_TransformedBoxTrace -29 ; CG_CM_TRANSFORMEDBOXTRACE
equ trap_CM_TransformedCapsuleTrace -136 ; CG_CM_TRANSFORMEDCAPSULETRACE
equ trap_CM_MarkFragments -30 ; CG_CM_MARKFRAGMENTS
equ trap_S_StopAllSounds -32 ; CG_S_STOPALLSOUNDS
equ trap_S_StartSound -31 ; CG_S_STARTSOUND
equ trap_S_StartLocalSound -33 ; CG_S_STARTLOCALSOUND
equ trap_S_ClearLoopingSounds -34 ; CG_S_CLEARLOOPINGSOUNDS
equ trap_S_AddLoopingSound -35 ; CG_S_ADDLOOPINGSOUND
equ trap_S_AddRealLoopingSound -132 ; CG_S_ADDREALLOOPINGSOUND
equ trap_S_StopLoopingSound -133 ; CG_S_STOPLOOPINGSOUND
equ trap_S_UpdateEntityPosition -36 ; CG_S_UPDATEENTITYPOSITION
equ trap_S_Respatialize -37 ; CG_S_RESPATIALIZE
equ trap_S_RegisterSound -38 ; CG_S_REGISTERSOUND
equ trap_S_StartBackgroundTrack -39 ; CG_S_STARTBACKGROUNDTRACK
equ trap_AS_AddPrecacheEntry -40 ; CG_AS_ADDPRECACHEENTRY
equ trap_AS_ParseSets -41 ; CG_AS_PARSESETS
equ trap_AS_UpdateAmbientSet -42 ; CG_AS_UPDATEAMBIENTSET
equ trap_AS_AddLocalSet -43 ; CG_AS_ADDLOCALSET
equ trap_AS_GetBModelSound -44 ; CG_AS_GETBMODELSOUND
equ trap_R_LoadWorldMap -45 ; CG_R_LOADWORLDMAP
equ trap_R_RegisterModel -46 ; CG_R_REGISTERMODEL
equ trap_R_RegisterSkin -47 ; CG_R_REGISTERSKIN
equ trap_R_RegisterShader -48 ; CG_R_REGISTERSHADER
equ trap_R_RegisterShaderNoMip -78 ; CG_R_REGISTERSHADERNOMIP
equ trap_R_RegisterFont -80 ; CG_R_REGISTERFONT
equ trap_R_ClearScene -49 ; CG_R_CLEARSCENE
equ trap_R_ClearDecals -50 ; CG_R_CLEARDECALS
equ trap_R_AddRefEntityToScene -51 ; CG_R_ADDREFENTITYTOSCENE
equ trap_R_AddPolyToScene -52 ; CG_R_ADDPOLYTOSCENE
equ trap_R_AddDecalToScene -53 ; CG_R_ADDDECALTOSCENE
equ trap_R_AddPolysToScene -139 ; CG_R_ADDPOLYSTOSCENE
equ trap_R_LightForPoint -122 ; CG_R_LIGHTFORPOINT
equ trap_R_AddLightToScene -54 ; CG_R_ADDLIGHTTOSCENE
equ trap_R_AddAdditiveLightToScene -137 ; CG_R_ADDADDITIVELIGHTTOSCENE
equ trap_R_RenderScene -55 ; CG_R_RENDERSCENE
equ trap_R_DrawVisualOverlay -56 ; CG_R_DRAWVISUALOVERLAY
equ trap_R_SetColor -57 ; CG_R_SETCOLOR
equ trap_R_DrawStretchPic -58 ; CG_R_DRAWSTRETCHPIC
equ trap_R_ModelBounds -59 ; CG_R_MODELBOUNDS
equ trap_R_LerpTag -60 ; CG_R_LERPTAG
equ trap_R_DrawRotatePic -61 ; CG_R_DRAWROTATEPIC
equ trap_R_DrawRotatePic2 -62 ; CG_R_DRAWROTATEPIC2
equ trap_R_RemapShader -128 ; CG_R_REMAP_SHADER
equ trap_R_GetLightStyle -129 ; CG_R_GET_LIGHT_STYLE
equ trap_R_SetLightStyle -130 ; CG_R_SET_LIGHT_STYLE
equ trap_R_GetTextWidth -65 ; CG_R_GETTEXTWIDTH
equ trap_R_GetTextHeight -66 ; CG_R_GETTEXTHEIGHT
equ trap_R_DrawText -63 ; CG_R_DRAWTEXT
equ trap_R_DrawTextWithCursor -64 ; CG_R_DRAWTEXTWITHCURSOR
equ trap_FX_AddLine -131 ; CG_FX_ADDLINE
equ trap_GetGlconfig -67 ; CG_GETGLCONFIG
equ trap_GetGameState -68 ; CG_GETGAMESTATE
equ trap_GetCurrentSnapshotNumber -69 ; CG_GETCURRENTSNAPSHOTNUMBER
equ trap_GetSnapshot -70 ; CG_GETSNAPSHOT
equ trap_GetDefaultState -71 ; CG_GETDEFAULTSTATE
equ trap_GetServerCommand -72 ; CG_GETSERVERCOMMAND
equ trap_GetCurrentCmdNumber -73 ; CG_GETCURRENTCMDNUMBER
equ trap_GetUserCmd -74 ; CG_GETUSERCMD
equ trap_SetUserCmdValue -75 ; CG_SETUSERCMDVALUE
equ trap_RW_SetTeam -76 ; CG_RW_SETTEAM
equ trap_ResetAutorun -77 ; CG_RESETAUTORUN
equ trap_MemoryRemaining -79 ; CG_MEMORY_REMAINING
equ trap_Key_IsDown -81 ; CG_KEY_ISDOWN
equ trap_Key_GetCatcher -82 ; CG_KEY_GETCATCHER
equ trap_Key_SetCatcher -83 ; CG_KEY_SETCATCHER
equ trap_Key_GetKey -84 ; CG_KEY_GETKEY
equ trap_PC_AddGlobalDefine -85 ; CG_PC_ADD_GLOBAL_DEFINE
equ trap_PC_LoadSource -86 ; CG_PC_LOAD_SOURCE
equ trap_PC_FreeSource -87 ; CG_PC_FREE_SOURCE
equ trap_PC_ReadToken -88 ; CG_PC_READ_TOKEN
equ trap_PC_SourceFileAndLine -89 ; CG_PC_SOURCE_FILE_AND_LINE
equ trap_PC_LoadGlobalDefines -90 ; CG_PC_LOAD_GLOBAL_DEFINES
equ trap_PC_RemoveAllGlobalDefines -91 ; CG_PC_REMOVE_ALL_GLOBAL_DEFINES
equ trap_S_StopBackgroundTrack -118 ; CG_S_STOPBACKGROUNDTRACK
equ trap_RealTime -119 ; CG_REAL_TIME
equ trap_SnapVector -120 ; CG_SNAPVECTOR
equ trap_CIN_PlayCinematic -123 ; CG_CIN_PLAYCINEMATIC
equ trap_CIN_StopCinematic -124 ; CG_CIN_STOPCINEMATIC
equ trap_CIN_RunCinematic -125 ; CG_CIN_RUNCINEMATIC
equ trap_CIN_DrawCinematic -126 ; CG_CIN_DRAWCINEMATIC
equ trap_CIN_SetExtents -127 ; CG_CIN_SETEXTENTS
equ trap_GetEntityToken -138 ; CG_GET_ENTITY_TOKEN
equ trap_R_inPVS -140 ; CG_R_INPVS
equ trap_FX_RegisterEffect -141 ; CG_FX_REGISTER_EFFECT
equ trap_FX_PlaySimpleEffect -142 ; CG_FX_PLAY_SIMPLE_EFFECT
equ trap_FX_PlayEffect -143 ; CG_FX_PLAY_EFFECT
equ trap_FX_PlayEntityEffect -144 ; CG_FX_PLAY_ENTITY_EFFECT
equ trap_FX_PlaySimpleEffectID -145 ; CG_FX_PLAY_SIMPLE_EFFECT_ID
equ trap_FX_PlayEffectID -146 ; CG_FX_PLAY_EFFECT_ID
equ trap_FX_PlayEntityEffectID -147 ; CG_FX_PLAY_ENTITY_EFFECT_ID
equ trap_FX_PlayBoltedEffectID -148 ; CG_FX_PLAY_BOLTED_EFFECT_ID
equ trap_FX_AddScheduledEffects -149 ; CG_FX_ADD_SCHEDULED_EFFECTS
equ trap_FX_Draw2DEffects -153 ; CG_FX_DRAW_2D_EFFECTS
equ trap_FX_InitSystem -150 ; CG_FX_INIT_SYSTEM
equ trap_FX_FreeSystem -151 ; CG_FX_FREE_SYSTEM
equ trap_FX_Reset -154 ; CG_FX_RESET
equ trap_FX_AdjustTime -152 ; CG_FX_ADJUST_TIME
equ trap_G2_ListModelSurfaces -156 ; CG_G2_LISTSURFACES
equ trap_G2_ListModelBones -155 ; CG_G2_LISTBONES
equ trap_G2_SetGhoul2ModelIndexes -163 ; CG_G2_SETMODELS
equ trap_G2API_CollisionDetect -190 ; CG_G2_COLLISIONDETECT
equ trap_G2API_AddBolt -157 ; CG_G2_ADDBOLT
equ trap_G2API_SetBoltInfo -158 ; CG_G2_SETBOLTON
equ trap_G2API_RemoveBolt -159 ; CG_G2_REMOVEBOLT
equ trap_G2API_AttachG2Model -160 ; CG_G2_ATTACHG2MODEL
equ trap_G2API_DetachG2Model -161 ; CG_G2_DETACHG2MODEL
equ trap_G2_HaveWeGhoul2Models -162 ; CG_G2_HAVEWEGHOULMODELS
equ trap_G2API_GetBoltMatrix -164 ; CG_G2_GETBOLT
equ trap_G2API_InitGhoul2Model -165 ; CG_G2_INITGHOUL2MODEL
equ trap_G2API_GetAnimFileNameIndex -185 ; CG_G2_GETANIMFILENAMEINDEX
equ trap_G2API_RegisterSkin -188 ; CG_G2_REGISTERSKIN
equ trap_G2API_SetSkin -189 ; CG_G2_SETSKIN
equ trap_G2API_CleanGhoul2Models -166 ; CG_G2_CLEANMODELS
equ trap_G2API_SetBoneAngles -167 ; CG_G2_ANGLEOVERRIDE
equ trap_G2API_SetBoneAnim -168 ; CG_G2_PLAYANIM
equ trap_G2API_GetBoneAnim -169 ; CG_G2_GETANIM
equ trap_G2API_SetSurfaceOnOff -170 ; CG_G2_SETSURFACEONOFF
equ trap_G2API_SetRootSurface -171 ; CG_G2_SETROOTSURFACE
equ trap_G2API_SetNewOrigin -172 ; CG_G2_SETNEWORIGIN
equ trap_G2API_GetGLAName -173 ; CG_G2_GETGLANAME
equ trap_G2API_CopyGhoul2Instance -174 ; CG_G2_COPYGHOUL2INSTANCE
equ trap_G2API_CopySpecificGhoul2Model -175 ; CG_G2_COPYSPECIFICGHOUL2MODEL
equ trap_G2API_DuplicateGhoul2Instance -176 ; CG_G2_DUPLICATEGHOUL2INSTANCE
equ trap_G2API_RemoveGhoul2Model -177 ; CG_G2_REMOVEGHOUL2MODEL
equ trap_G2API_AddSkinGore -178 ; CG_G2_ADDSKINGORE
equ trap_G2API_ClearSkinGore -179 ; CG_G2_CLEARSKINGORE
equ trap_G2API_SetGhoul2ModelFlags -180 ; CG_G2_SETGHOUL2MODELFLAGS
equ trap_G2API_GetGhoul2ModelFlags -181 ; CG_G2_GETGHOUL2MODELFLAGS
equ trap_G2API_SetGhoul2ModelFlagsByIndex -182 ; CG_G2_SETGHOUL2MODELFLAGSBYINDEX
equ trap_G2API_GetGhoul2ModelFlagsByIndex -183 ; CG_G2_GETGHOUL2MODELFLAGSBYINDEX
equ trap_G2API_GetNumModels -184 ; CG_G2_GETNUMMODELS
equ trap_G2API_FindBoltIndex -186 ; CG_G2_FINDBOLTINDEX
equ trap_G2API_GetBoltIndex -187 ; CG_G2_GETBOLTINDEX
equ trap_MAT_Init -192 ; CG_MAT_CACHE
equ trap_MAT_Reset -191 ; CG_MAT_RESET
equ trap_MAT_GetSound -193 ; CG_MAT_GET_SOUND
equ trap_MAT_GetDecal -194 ; CG_MAT_GET_DECAL
equ trap_MAT_GetDecalScale -195 ; CG_MAT_GET_DECAL_SCALE
equ trap_MAT_GetEffect -196 ; CG_MAT_GET_EFFECT
equ trap_MAT_GetDebris -197 ; CG_MAT_GET_DEBRIS
equ trap_MAT_GetDebrisScale -198 ; CG_MAT_GET_DEBRIS_SCALE
equ trap_GP_Parse -205 ; GP_PARSE
equ trap_GP_ParseFile -206 ; GP_PARSE_FILE
equ trap_GP_Clean -207 ; GP_CLEAN
equ trap_GP_Delete -208 ; GP_DELETE
equ trap_GP_GetBaseParseGroup -209 ; GP_GET_BASE_PARSE_GROUP
equ trap_GPG_GetName -210 ; GPG_GET_NAME
equ trap_GPG_GetNext -211 ; GPG_GET_NEXT
equ trap_GPG_GetInOrderNext -212 ; GPG_GET_INORDER_NEXT
equ trap_GPG_GetInOrderPrevious -213 ; GPG_GET_INORDER_PREVIOUS
equ trap_GPG_GetPairs -214 ; GPG_GET_PAIRS
equ trap_GPG_GetInOrderPairs -215 ; GPG_GET_INORDER_PAIRS
equ trap_GPG_GetSubGroups -216 ; GPG_GET_SUBGROUPS
equ trap_GPG_GetInOrderSubGroups -217 ; GPG_GET_INORDER_SUBGROUPS
equ trap_GPG_FindSubGroup -218 ; GPG_FIND_SUBGROUP
equ trap_GPG_FindPair -219 ; GPG_FIND_PAIR
equ trap_GPG_FindPairValue -220 ; GPG_FIND_PAIRVALUE
equ trap_GPV_GetName -221 ; GPV_GET_NAME
equ trap_GPV_GetNext -222 ; GPV_GET_NEXT
equ trap_GPV_GetInOrderNext -223 ; GPV_GET_INORDER_NEXT
equ trap_GPV_GetInOrderPrevious -224 ; GPV_GET_INORDER_PREVIOUS
equ trap_GPV_IsList -225 ; GPV_IS_LIST
equ trap_GPV_GetTopValue -226 ; GPV_GET_TOP_VALUE
equ trap_GPV_GetList -227 ; GPV_GET_LIST
equ trap_CM_TM_Create -199 ; CG_CM_TM_CREATE
equ trap_CM_TM_AddBuilding -200 ; CG_CM_TM_ADDBUILDING
equ trap_CM_TM_AddSpot -201 ; CG_CM_TM_ADDSPOT
equ trap_CM_TM_AddTarget -202 ; CG_CM_TM_ADDTARGET
equ trap_CM_TM_Upload -203 ; CG_CM_TM_UPLOAD
equ trap_CM_TM_ConvertPosition -204 ; CG_CM_TM_CONVERT_POS
equ trap_CM_RegisterTerrain -228 ; CG_CM_REGISTER_TERRAIN
equ trap_RE_InitRendererTerrain -229 ; CG_RE_INIT_RENDERER_TERRAIN
equ trap_CG_RegisterSharedMemory -230 ; CG_SET_SHARED_BUFFER
equ trap_FS_GetFileList -15 ; CG_FS_GETFILELIST
equ trap_VM_LocalAlloc -231 ; CG_VM_LOCALALLOC
equ trap_VM_LocalAllocUnaligned -232 ; CG_VM_LOCALALLOCUNALIGNED
equ trap_VM_LocalTempAlloc -233 ; CG_VM_LOCALTEMPALLOC
equ trap_VM_LocalTempFree -234 ; CG_VM_LOCALTEMPFREE
equ trap_VM_LocalStringAlloc -235 ; CG_VM_LOCALSTRINGALLOC
equ trap_UI_CloseAll -237 ; CG_UI_CLOSEALL
equ trap_UI_SetActiveMenu -236 ; CG_UI_SETACTIVEMENU
; hardcoded functions
equ memset -101 ; CG_MEMSET
equ memcpy -102 ; CG_MEMCPY
equ strncpy -103 ; CG_STRNCPY
equ sin -104 ; CG_SIN
equ cos -105 ; CG_COS
equ atan2 -106 ; CG_ATAN2
equ sqrt -107 ; CG_SQRT
equ matrixmultiply -116 ; CG_MATRIXMULTIPLY
equ anglevectors -108 ; CG_ANGLEVECTORS
equ perpendicularvector -109 ; CG_PERPENDICULARVECTOR
equ floor -110 ; CG_FLOOR
equ ceil -111 ; CG_CEIL
equ acos -114 ; CG_ACOS
equ asin -115 ; CG_ASIN

1056
code/cgame/cg_syscalls.c Normal file

File diff suppressed because it is too large Load Diff

1454
code/cgame/cg_view.c Normal file

File diff suppressed because it is too large Load Diff

474
code/cgame/cg_weaponinit.c Normal file
View File

@ -0,0 +1,474 @@
// Copyright (C) 2001-2002 Raven Software, Inc.
//
// cg_weaponinit.c -- weapon initialization
#include "cg_local.h"
#include "../game/bg_weapons.h"
// FIMXE: This is defined in a C++ header file.
// We need to break it up or somethin so we don't have mutliple defs.
#define GHOUL2_NORENDER 2
/*
=================
CG_RegisterItemVisuals
The server says this item is used on this level
=================
*/
void CG_RegisterItemVisuals( int itemNum )
{
itemInfo_t *itemInfo;
gitem_t *item;
char simpleName[MAX_QPATH];
if ( itemNum < 0 || itemNum >= bg_numItems )
{
Com_Error( ERR_FATAL, "CG_RegisterItemVisuals: itemNum %d out of range [0-%d]", itemNum, bg_numItems-1 );
}
itemInfo = &cg_items[ itemNum ];
if ( itemInfo->registered )
{
return;
}
item = &bg_itemlist[ itemNum ];
memset( itemInfo, 0, sizeof( &itemInfo ) );
itemInfo->registered = qtrue;
itemInfo->models[0] = trap_R_RegisterModel( item->world_model[0] );
// Check to see if its a ghoul model we loaded
if (!Q_stricmp(&item->world_model[0][strlen(item->world_model[0]) - 4], ".glm"))
{
trap_G2API_InitGhoul2Model(&itemInfo->g2Models[0], item->world_model[0], 0 , 0, 0, 0, 0);
itemInfo->radius[0] = 60;
// Special case to make sure some sufaces are show that should be
switch ( item->giTag )
{
case WP_AK74_ASSAULT_RIFLE:
trap_G2API_SetSurfaceOnOff( itemInfo->g2Models[0], 0, "bayonet_off", 0 );
break;
case WP_M4_ASSAULT_RIFLE:
trap_G2API_SetSurfaceOnOff( itemInfo->g2Models[0], 0, "m203_off", 0 );
break;
}
}
itemInfo->icon = trap_R_RegisterShaderNoMip( item->icon );
if (item->icon[0])
{
Com_sprintf(simpleName, sizeof(simpleName), "%s_simple", item->icon);
itemInfo->mSimpleIcon = trap_R_RegisterShader(simpleName);
}
else
{
itemInfo->mSimpleIcon = 0;
}
if ( item->giType == IT_WEAPON )
{
CG_RegisterWeapon( item->giTag );
}
}
/*
=================
CG_RegisterWeapon
The server says this item is used on this level
=================
*/
void CG_RegisterWeapon(int weaponNum)
{
weaponInfo_t *weaponInfo;
weaponData_t *weaponDat;
TWeaponModel *weaponModel;
TOptionalWeapon *optionalPart;
gitem_t *item,*ammo;
TWeaponParseInfo *wPI;
int weaponIndex; // model index for view weapon models
int bufferIndex; // weapon + buffer + rhand [+ lhand ]
int rHandIndex;
int lHandIndex;
int boltonIndex;
int boltIndex;
int soundSet, i;
int *indexes;
if(weaponNum==0)
{
return;
}
boltonIndex = -1;
assert(weaponNum < WP_NUM_WEAPONS);
weaponInfo=&cg_weapons[weaponNum];
if(weaponInfo->registered)
{
return;
}
memset(weaponInfo,0,sizeof(*weaponInfo));
// Register the item visuals (icons etc).
weaponInfo->item = item = BG_FindWeaponItem ( weaponNum );
// Must be initial loading
if ( !weaponInfo->registered )
{
CG_LoadingItem( item - bg_itemlist );
}
// Ok, successfully registered the entire weapon.
weaponInfo->registered=qtrue;
weaponDat = &weaponData[weaponNum];
if(item->classname)
{
// Hmmm... this needs some work... some of it looks if now.
CG_RegisterItemVisuals( item - bg_itemlist );
}
else
{
Com_Error( ERR_FATAL, "CG_RegisterWeapon: Couldn't find weapon item %i", weaponNum);
}
// Register the weapon's world ammo model.
for ( ammo = bg_itemlist + 1 ; ammo->classname ; ammo++ )
{
if ( ammo->giType == IT_AMMO && ammo->giTag == weaponNum )
{
break;
}
}
if( ammo->classname && ammo->world_model[0] )
{
trap_G2API_InitGhoul2Model(&weaponInfo->ammoG2Model,ammo->world_model[0],0,0,0,0,0);
}
// Create the world model.
weaponIndex = trap_G2API_InitGhoul2Model(&weaponInfo->weaponG2Model,weaponDat->worldModel,0,0,0,0,0);
if(!trap_G2_HaveWeGhoul2Models(weaponInfo->weaponG2Model))
{
Com_Printf("CG_RegisterWeapon: Unable to load weapon world model: %s\n", weaponDat->worldModel);
}
// Register the weapon model...
indexes=weaponInfo->viewG2Indexes;
for(i=0;i<8;i++)
{
indexes[i]=-1;
}
wPI=&weaponParseInfo[weaponNum];
// Create the view weapon model in slot 0.
indexes[0] = weaponIndex = trap_G2API_InitGhoul2Model(&weaponInfo->viewG2Model,
wPI->mWeaponModel.mModel,0,0,0,0,0);
// Now build and assemble all the other bits.
if(trap_G2_HaveWeGhoul2Models(weaponInfo->viewG2Model))
{
// Add a bolt to the weapon so buffer can be bolted on.
boltIndex=trap_G2API_AddBolt(weaponInfo->viewG2Model,weaponIndex,wPI->mWeaponModel.mBufferBoltToBone);
// Every view weapon has a buffer, create this in slot 1.
indexes[1]=bufferIndex=trap_G2API_InitGhoul2Model(&weaponInfo->viewG2Model,
wPI->mWeaponModel.mBufferModel,
weaponIndex+1,0,0,0,0);
// Bolt the buffer to the weapon.
trap_G2API_AttachG2Model(weaponInfo->viewG2Model,bufferIndex,
weaponInfo->viewG2Model,boltIndex,weaponIndex);
// Right hand??
if(wPI->mWeaponModel.mRightHandsBoltToBone[0])
{
// Add a right hand bolt to the buffer.
boltIndex=trap_G2API_AddBolt(weaponInfo->viewG2Model,bufferIndex,
wPI->mWeaponModel.mRightHandsBoltToBone);
// Right hand.. create this now in slot 2.
indexes[2]=rHandIndex=trap_G2API_InitGhoul2Model(&weaponInfo->viewG2Model,
"models/weapons/rhand/rhand.glm",
weaponIndex+2,0,0,0,0);
// Bolt the right hand to the buffer.
trap_G2API_AttachG2Model(weaponInfo->viewG2Model,rHandIndex,weaponInfo->viewG2Model,
boltIndex,bufferIndex);
}
// Left hand??
if(wPI->mWeaponModel.mLeftHandsBoltToBone[0])
{
// Add a left hand bolt to the buffer.
boltIndex=trap_G2API_AddBolt(weaponInfo->viewG2Model,bufferIndex,
wPI->mWeaponModel.mLeftHandsBoltToBone);
// Left hand.. create this now in slot 3.
indexes[3]=lHandIndex=trap_G2API_InitGhoul2Model(&weaponInfo->viewG2Model,
"models/weapons/lhand/lhand.glm",
weaponIndex+3,0,0,0,0);
// Bolt the left hand to the buffer.
trap_G2API_AttachG2Model(weaponInfo->viewG2Model,lHandIndex,weaponInfo->viewG2Model,
boltIndex,bufferIndex);
}
// Boltons like the M4's grenade launcher?
if(wPI->mWeaponModel.mBolton)
{
// Add a bolton bolt to the buffer.
boltIndex=trap_G2API_AddBolt(weaponInfo->viewG2Model,bufferIndex,
wPI->mWeaponModel.mBolton->mBoltToBone);
// Bolton.. create this now in slot 4.
indexes[4]=boltonIndex=trap_G2API_InitGhoul2Model(&weaponInfo->viewG2Model,
wPI->mWeaponModel.mBolton->mModel,
weaponIndex+4,0,0,0,0);
// Bolt the bolton to the buffer.
if ( boltonIndex != -1 )
{
trap_G2API_AttachG2Model(weaponInfo->viewG2Model,boltonIndex,weaponInfo->viewG2Model,
boltIndex,bufferIndex);
}
}
// Turn of any weapon surfaces that are never seen.
weaponModel=&wPI->mWeaponModel;
i=0;
while(weaponModel->mRightSideSurfaces[i])
{
trap_G2API_SetSurfaceOnOff(weaponInfo->viewG2Model,weaponInfo->viewG2Indexes[0],
weaponModel->mRightSideSurfaces[i],GHOUL2_NORENDER);
i++;
}
i=0;
while(weaponModel->mFrontSurfaces[i])
{
trap_G2API_SetSurfaceOnOff(weaponInfo->viewG2Model,weaponInfo->viewG2Indexes[0],
weaponModel->mFrontSurfaces[i],GHOUL2_NORENDER);
i++;
}
if(weaponModel->mBolton && boltonIndex != -1 )
{
i=0;
while(weaponModel->mBolton->mRightSide[i])
{
trap_G2API_SetSurfaceOnOff(weaponInfo->viewG2Model,boltonIndex,
weaponModel->mBolton->mRightSide[i],GHOUL2_NORENDER);
i++;
}
}
// Turn off optional parts as we don't want em.
optionalPart=weaponModel->mOptionalList;
while(optionalPart)
{
// No real way of knowing what single player intended so we have to
// hard-code 'em.
if((!strcmp(optionalPart->mName,"lasersight"))||
(!strcmp(optionalPart->mName,"silencer"))||
(!strcmp(optionalPart->mName,"utl")))
{
i=0;
while(optionalPart->mSurfaces[i])
{
trap_G2API_SetSurfaceOnOff(weaponInfo->viewG2Model,weaponInfo->viewG2Indexes[0],
optionalPart->mSurfaces[i],GHOUL2_NORENDER);
i++;
}
}
optionalPart=optionalPart->mNext;
}
}
else
{
Com_Printf("CG_RegisterWeapon: Unable to load weapon view model: %s\n", wPI->mWeaponModel.mModel);
}
weaponInfo->attack[ATTACK_NORMAL].missileTrailFunc = CG_ProjectileThink;
weaponInfo->attack[ATTACK_ALTERNATE].missileTrailFunc = CG_ProjectileThink;
// Register weapon list menu icons.
if (weaponDat->menuImage[0])
{
weaponInfo->weaponIcon = trap_R_RegisterShader( va( "gfx/menus/%s", weaponDat->menuImage) );
}
// Register the alternate weapon ammo icon for the hud
if (weaponDat->attack[ATTACK_ALTERNATE].icon[0] )
{
weaponInfo->attack[ATTACK_ALTERNATE].ammoIcon = trap_R_RegisterShader( va( "gfx/menus/%s", weaponDat->attack[ATTACK_ALTERNATE].icon ) );
}
// Register attack stuff
for ( i = ATTACK_NORMAL; i < ATTACK_MAX; i ++ )
{
attackData_t* attackData = &weaponDat->attack[i];
attackInfo_t* attackInfo = &weaponInfo->attack[i];
// Primary muzzle-flash.
if (attackData->muzzleEffect[0])
attackInfo->muzzleEffect = trap_FX_RegisterEffect(attackData->muzzleEffect);
if (attackData->muzzleEffectInWorld[0])
attackInfo->muzzleEffectInWorld = trap_FX_RegisterEffect(attackData->muzzleEffectInWorld);
if (!attackInfo->muzzleEffectInWorld)
attackInfo->muzzleEffectInWorld = attackInfo->muzzleEffect;
// Primary shell eject.
if (attackData->shellEject[0])
attackInfo->shellEject = trap_FX_RegisterEffect(attackData->shellEject);
if (attackData->tracerEffect[0])
attackInfo->tracerEffect = trap_FX_RegisterEffect(attackData->tracerEffect);
// Primary explosion.
if (attackData->explosionEffect[0])
attackInfo->explosionEffect = trap_FX_RegisterEffect(attackData->explosionEffect);
if (attackData->explosionSound[0])
attackInfo->explosionSound = trap_S_RegisterSound(attackData->explosionSound);
if (attackData->missileG2Model[0])
trap_G2API_InitGhoul2Model(&attackInfo->missileG2Model,attackData->missileG2Model,0,0,0,0,0);
// Add the bolts for muzzle flash and shell eject onto the view model.
if (trap_G2_HaveWeGhoul2Models(weaponInfo->viewG2Model))
{
// shell eject bone.
if ( attackData->ejectBone[0] )
{
attackInfo->shellEjectBoltView =
trap_G2API_AddBolt(weaponInfo->viewG2Model, 1, attackData->ejectBone);
}
// Muzzle flash bone.
attackInfo->muzzleFlashBoltView = -1;
if(attackData->muzzleEffect[0])
{
if ( attackData->muzzleEffectBone[0] )
{
attackInfo->muzzleFlashBoltView =
trap_G2API_AddBolt(weaponInfo->viewG2Model, 1, attackData->muzzleEffectBone );
}
else if (wPI->mWeaponModel.mBufferMuzzle[0])
{
attackInfo->muzzleFlashBoltView =
trap_G2API_AddBolt(weaponInfo->viewG2Model, 1, wPI->mWeaponModel.mBufferMuzzle);
}
}
}
// Add the bolts for muzzle flash and shell eject onto the world model.
if (trap_G2_HaveWeGhoul2Models(weaponInfo->weaponG2Model))
{
// shell eject bone.
if (attackData->ejectBone[0])
{
attackInfo->shellEjectBoltWorld =
trap_G2API_AddBolt(weaponInfo->weaponG2Model, 0, attackData->ejectBone);
}
else
{
attackInfo->shellEjectBoltWorld = -1;
}
// Muzzle flash bone.
attackInfo->muzzleFlashBoltWorld = -1;
if ( attackData->muzzleEffectBone[0] )
{
attackInfo->muzzleFlashBoltWorld =
trap_G2API_AddBolt(weaponInfo->weaponG2Model, 0, attackData->muzzleEffectBone );
}
else if (wPI->mWeaponModel.mBufferMuzzle[0])
{
attackInfo->muzzleFlashBoltWorld =
trap_G2API_AddBolt(weaponInfo->weaponG2Model, 0, wPI->mWeaponModel.mBufferMuzzle);
}
}
}
// Register sounds for weapon.
for (soundSet = 0; soundSet < MAX_WEAPON_SOUNDS; soundSet++)
{
if (Q_stricmp(wPI->mSoundNames[soundSet], "fire")==0)
{
for (i=0; i<MAX_WEAPON_SOUND_SLOTS; i++)
{
if (wPI->mSounds[soundSet][i][0])
{
weaponInfo->attack[ATTACK_NORMAL].flashSound[i] = trap_S_RegisterSound(wPI->mSounds[soundSet][i]);
}
}
}
else if (Q_stricmp(wPI->mSoundNames[soundSet], "altfire")==0)
{
for (i=0; i<MAX_WEAPON_SOUND_SLOTS; i++)
{
if (wPI->mSounds[soundSet][i][0])
weaponInfo->attack[ATTACK_ALTERNATE].flashSound[i] = trap_S_RegisterSound(wPI->mSounds[soundSet][i]);
}
}
else
{
// All other sounds.
for (i=0; i<MAX_WEAPON_SOUND_SLOTS; i++)
{
if (wPI->mSounds[soundSet][i][0])
weaponInfo->otherWeaponSounds[soundSet][i]=trap_S_RegisterSound(wPI->mSounds[soundSet][i]);
}
}
}
// Special hard coded stuff
switch ( weaponNum )
{
case WP_KNIFE:
{
attackInfo_t* attackInfo = &weaponInfo->attack[ATTACK_ALTERNATE];
attackInfo->missileSound = trap_S_RegisterSound ( "sound/weapons/knife/throw_loop" );
break;
}
case WP_RPG7_LAUNCHER:
{
attackInfo_t* attackInfo = &weaponInfo->attack[ATTACK_NORMAL];
attackInfo->missileSound = trap_S_RegisterSound ( "sound/weapons/rpg7/flyby" );
break;
}
}
}
/*
=================
CG_ShutDownWeapons
Clean out any g2 models
=================
*/
void CG_ShutDownWeapons ( void )
{
int i;
attackType_t a;
for (i=0; i < WP_NUM_WEAPONS; i++)
{
// free all ghoul2 models
trap_G2API_CleanGhoul2Models(&cg_weapons[i].weaponG2Model);
trap_G2API_CleanGhoul2Models(&cg_weapons[i].viewG2Model);
trap_G2API_CleanGhoul2Models(&cg_weapons[i].ammoG2Model);
for ( a = ATTACK_NORMAL; a < ATTACK_MAX; a ++ )
{
trap_G2API_CleanGhoul2Models(&cg_weapons[i].attack[a].missileG2Model);
}
}
}

1783
code/cgame/cg_weapons.c Normal file

File diff suppressed because it is too large Load Diff

83
code/cgame/cgame.bat Normal file
View File

@ -0,0 +1,83 @@
@set include=
del /q vm
mkdir vm
cd vm
set cc=..\..\..\bin\sof2lcc -DQ3_VM -DMISSIONPACK -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui %1
%cc% ../../game/bg_misc.c
@if errorlevel 1 goto quit
%cc% ../../game/bg_weapons.c
@if errorlevel 1 goto quit
%cc% ../../game/bg_player.c
@if errorlevel 1 goto quit
%cc% ../../game/bg_pmove.c
@if errorlevel 1 goto quit
%cc% ../../game/bg_slidemove.c
@if errorlevel 1 goto quit
%cc% ../../game/bg_lib.c
@if errorlevel 1 goto quit
%cc% ../../game/bg_gametype.c
@if errorlevel 1 goto quit
%cc% ../../game/q_math.c
@if errorlevel 1 goto quit
%cc% ../../game/q_shared.c
@if errorlevel 1 goto quit
%cc% ../cg_consolecmds.c
@if errorlevel 1 goto quit
%cc% ../cg_draw.c
@if errorlevel 1 goto quit
%cc% ../cg_drawtools.c
@if errorlevel 1 goto quit
%cc% ../cg_effects.c
@if errorlevel 1 goto quit
%cc% ../cg_ents.c
@if errorlevel 1 goto quit
%cc% ../cg_event.c
@if errorlevel 1 goto quit
%cc% ../cg_gametype.c
@if errorlevel 1 goto quit
%cc% ../cg_gore.c
@if errorlevel 1 goto quit
%cc% ../cg_info.c
@if errorlevel 1 goto quit
%cc% ../cg_light.c
@if errorlevel 1 goto quit
%cc% ../cg_localents.c
@if errorlevel 1 goto quit
%cc% ../cg_main.c
@if errorlevel 1 goto quit
%cc% ../cg_miscents.c
@if errorlevel 1 goto quit
%cc% ../cg_players.c
@if errorlevel 1 goto quit
%cc% ../cg_playerstate.c
@if errorlevel 1 goto quit
%cc% ../cg_predict.c
@if errorlevel 1 goto quit
%cc% ../cg_scoreboard.c
@if errorlevel 1 goto quit
%cc% ../cg_servercmds.c
@if errorlevel 1 goto quit
%cc% ../cg_snapshot.c
@if errorlevel 1 goto quit
%cc% ../cg_view.c
@if errorlevel 1 goto quit
%cc% ../cg_weaponinit.c
@if errorlevel 1 goto quit
%cc% ../cg_weapons.c
@if errorlevel 1 goto quit
%cc% ../../ui/ui_shared.c
@if errorlevel 1 goto quit
%cc% ../cg_newDraw.c
@if errorlevel 1 goto quit
..\..\..\bin\sof2asm -f ../cgame
@if errorlevel 1 goto quit
mkdir "..\..\..\base\vm"
copy *.map "..\..\..\base\vm"
copy *.qvm "..\..\..\base\vm"
:quit
cd ..

35
code/cgame/cgame.q3asm Normal file
View File

@ -0,0 +1,35 @@
-o "sof2mp_cgame"
cg_main
..\cg_syscalls
cg_consolecmds
cg_draw
cg_drawtools
cg_effects
cg_ents
cg_event
cg_gametype
cg_gore
cg_info
cg_light
cg_localents
cg_miscents
cg_players
cg_playerstate
cg_predict
cg_scoreboard
cg_servercmds
cg_snapshot
cg_view
cg_weaponinit
cg_weapons
bg_slidemove
bg_weapons
bg_player
bg_pmove
bg_lib
bg_misc
bg_gametype
q_math
q_shared
ui_shared
cg_newDraw

View File

@ -0,0 +1,3 @@
EXPORTS
vmMain
dllEntry

760
code/cgame/sof2_cgame.dsp Normal file
View File

@ -0,0 +1,760 @@
# Microsoft Developer Studio Project File - Name="SoF2cgame" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=SoF2cgame - Win32 SH Debug SoF2
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "sof2_cgame.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "sof2_cgame.mak" CFG="SoF2cgame - Win32 SH Debug SoF2"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "SoF2cgame - Win32 Release SoF2" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "SoF2cgame - Win32 Debug SoF2" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "SoF2cgame - Win32 SH Debug SoF2" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "SoF2cgame___Win32_Release_TA"
# PROP BASE Intermediate_Dir "SoF2cgame___Win32_Release_TA"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "../Release"
# PROP Intermediate_Dir "..\Release/SoF2cgame"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /W4 /GX /O2 /D "WIN32" /D "NDebug SoF2" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /G6 /W4 /GX /Zi /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "MISSIONPACK" /D "_SOF2" /D "CGAME" /YX /FD /c
# SUBTRACT CPP /Fr
# ADD BASE MTL /nologo /D "NDebug SoF2" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDebug SoF2" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDebug SoF2"
# ADD RSC /l 0x409 /d "NDebug SoF2"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /machine:I386 /out:"../Release/SoF2cgamex86.dll"
# SUBTRACT BASE LINK32 /debug
# ADD LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map:"..\Release/sof2mp_cgamex86.map" /debug /machine:I386 /out:"../Release/sof2mp_cgamex86.dll"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "SoF2cgame___Win32_Debug_TA"
# PROP BASE Intermediate_Dir "SoF2cgame___Win32_Debug_TA"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\Debug"
# PROP Intermediate_Dir "..\Debug\SoF2cgame"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G5 /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_Debug SoF2" /D "_WINDOWS" /FR /YX /FD /c
# ADD CPP /nologo /G5 /MTd /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "MISSIONPACK" /D "_SOF2" /D "CGAME" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_Debug SoF2" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_Debug SoF2" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_Debug SoF2"
# ADD RSC /l 0x409 /d "_Debug SoF2"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /debug /machine:I386 /out:"..\Debug/SoF2cgamex86.dll"
# SUBTRACT BASE LINK32 /profile /nodefaultlib
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x30000000" /subsystem:windows /dll /map:"..\Debug\sof2mp_cgamex86.map" /debug /machine:I386 /def:".\SoF2_cgame.def" /out:"..\Debug\sof2mp_cgamex86.dll"
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "SoF2cgame___Win32_SH_Debug_SoF2"
# PROP BASE Intermediate_Dir "SoF2cgame___Win32_SH_Debug_SoF2"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "SoF2cgame___Win32_SH_Debug_SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G5 /MTd /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "MISSIONPACK" /D "_SOF2" /FR /YX /FD /c
# ADD CPP /nologo /G5 /MTd /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "MISSIONPACK" /D "_SOF2" /D "MEM_DEBUG" /D "CGAME" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_Debug SoF2" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_Debug SoF2" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_Debug SoF2"
# ADD RSC /l 0x409 /d "_Debug SoF2"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map:"..\Debug\sof2mp_cgamex86.map" /debug /machine:I386 /def:".\SoF2_cgame.def" /out:"..\Debug\sof2mp_cgamex86.dll"
# SUBTRACT BASE LINK32 /pdb:none
# ADD LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /pdb:"..\SHDebug/sof2mp_cgamex86.pdb" /map:"..\SHDebug\sof2mp_cgamex86.map" /debug /machine:I386 /def:".\SoF2_cgame.def" /out:"..\SHDebug\sof2mp_cgamex86.dll"
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "SoF2cgame - Win32 Release SoF2"
# Name "SoF2cgame - Win32 Debug SoF2"
# Name "SoF2cgame - Win32 SH Debug SoF2"
# Begin Group "Source Files"
# PROP Default_Filter "c"
# Begin Source File
SOURCE=..\game\bg_gametype.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\bg_lib.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
# PROP BASE Exclude_From_Build 1
# PROP Exclude_From_Build 1
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
# PROP BASE Exclude_From_Build 1
# PROP Exclude_From_Build 1
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP BASE Exclude_From_Build 1
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
# PROP Exclude_From_Build 1
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\bg_misc.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\bg_player.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\bg_pmove.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\bg_slidemove.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\bg_weapons.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_consolecmds.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_draw.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_drawtools.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_effects.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_ents.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_event.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_gametype.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_gore.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_info.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_light.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_localents.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_main.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_miscents.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_newDraw.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_players.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_playerstate.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_predict.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_scoreboard.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_servercmds.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_snapshot.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_syscalls.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_view.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_weaponinit.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\cg_weapons.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\q_math.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\q_shared.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\ui\ui_shared.c
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP Intermediate_Dir "..\SHDebug\SoF2cgame"
!ENDIF
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h"
# Begin Source File
SOURCE=.\animtable.h
# End Source File
# Begin Source File
SOURCE=..\game\bg_local.h
# End Source File
# Begin Source File
SOURCE=..\game\bg_public.h
# End Source File
# Begin Source File
SOURCE=..\game\bg_weapons.h
# End Source File
# Begin Source File
SOURCE=.\cg_lights.h
# End Source File
# Begin Source File
SOURCE=.\cg_local.h
# End Source File
# Begin Source File
SOURCE=.\cg_public.h
# End Source File
# Begin Source File
SOURCE=..\qcommon\disablewarnings.h
# End Source File
# Begin Source File
SOURCE=..\ghoul2\G2.h
# End Source File
# Begin Source File
SOURCE=..\ghoul2\G2_gore_shared.h
# End Source File
# Begin Source File
SOURCE=..\game\g_local.h
# End Source File
# Begin Source File
SOURCE=..\game\g_public.h
# End Source File
# Begin Source File
SOURCE=..\game\g_team.h
# End Source File
# Begin Source File
SOURCE=..\ui\keycodes.h
# End Source File
# Begin Source File
SOURCE=..\..\ui\menudef.h
# End Source File
# Begin Source File
SOURCE=..\game\q_shared.h
# End Source File
# Begin Source File
SOURCE=..\game\surfaceflags.h
# End Source File
# Begin Source File
SOURCE=..\qcommon\tags.h
# End Source File
# Begin Source File
SOURCE=.\tr_types.h
# End Source File
# Begin Source File
SOURCE=..\ui\ui_shared.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\cgame.bat
# End Source File
# Begin Source File
SOURCE=.\cgame.q3asm
# End Source File
# Begin Source File
SOURCE=.\SoF2_cgame.def
!IF "$(CFG)" == "SoF2cgame - Win32 Release SoF2"
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 Debug SoF2"
# PROP Exclude_From_Build 1
!ELSEIF "$(CFG)" == "SoF2cgame - Win32 SH Debug SoF2"
# PROP BASE Exclude_From_Build 1
# PROP Exclude_From_Build 1
!ENDIF
# End Source File
# End Target
# End Project

338
code/cgame/tr_types.h Normal file
View File

@ -0,0 +1,338 @@
// Copyright (C) 2001-2002 Raven Software.
//
#ifndef __TR_TYPES_H
#define __TR_TYPES_H
#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces
#define MAX_ENTITIES 1023 // can't be increased without changing drawsurf bit packing
#define MAX_MINI_ENTITIES 1024
// renderfx flags
#define RF_MINLIGHT 1 // allways have some light (viewmodel, some items)
#define RF_THIRD_PERSON 2 // don't draw through eyes, only mirrors (player bodies, chat sprites)
#define RF_FIRST_PERSON 4 // only draw through eyes (view weapon, damage blood blob)
#define RF_DEPTHHACK 8 // for view weapon Z crunching
#define RF_NOSHADOW 64 // don't add stencil shadows
#define RF_LIGHTING_ORIGIN 128 // use refEntity->lightingOrigin instead of refEntity->origin
// for lighting. This allows entities to sink into the floor
// with their origin going solid, and allows all parts of a
// player to get the same lighting
#define RF_SHADOW_PLANE 256 // use refEntity->shadowPlane
#define RF_WRAP_FRAMES 512 // mod the model frames by the maxframes to allow continuous
// animation without needing to know the frame count
#define RF_FORKED 0x00001000 // override lightning to have forks
#define RF_TAPERED 0x00002000 // lightning tapers
#define RF_GROW 0x00004000 // lightning grows from start to end during its life
#define RF_NO_FOG 0x00008000 // no fog for g2 models
// refdef flags
#define RDF_NOWORLDMODEL 1 // used for player configuration screen
#define RDF_PROJECTION2D 2
#define RDF_HYPERSPACE 4 // teleportation effect
typedef byte color4ub_t[4];
typedef struct {
vec3_t xyz;
float st[2];
byte modulate[4];
} polyVert_t;
typedef struct poly_s {
qhandle_t hShader;
int numVerts;
polyVert_t *verts;
} poly_t;
typedef enum {
RT_MODEL,
RT_POLY,
RT_SPRITE,
RT_ORIENTED_QUAD,
RT_BEAM,
RT_ELECTRICITY,
RT_PORTALSURFACE, // doesn't draw anything, just info for portals
RT_LINE,
RT_ORIENTEDLINE,
RT_CYLINDER,
RT_ENT_CHAIN,
RT_MAX_REF_ENTITY_TYPE
} refEntityType_t;
typedef struct miniRefEntity_s
{
refEntityType_t reType;
int renderfx;
qhandle_t hModel; // opaque type outside refresh
// most recent data
vec3_t axis[3]; // rotation vectors
qboolean nonNormalizedAxes; // axis are not normalized, i.e. they have scale
vec3_t origin; // also used as MODEL_BEAM's "from"
// previous data for frame interpolation
vec3_t oldorigin; // also used as MODEL_BEAM's "to"
// texturing
qhandle_t customShader; // use one image for the entire thing
// misc
byte shaderRGBA[4]; // colors used by rgbgen entity shaders
vec2_t shaderTexCoord; // texture coordinates used by tcMod entity modifiers
// extra sprite information
float radius;
float rotation; // size 2 for RT_CYLINDER or number of verts in RT_ELECTRICITY
// misc
float shaderTime; // subtracted from refdef time to control effect start times
int frame; // also used as MODEL_BEAM's diameter
} miniRefEntity_t;
#pragma warning (disable : 4201 )
typedef struct {
// this stucture must remain identical as the miniRefEntity_t
//
//
refEntityType_t reType;
int renderfx;
qhandle_t hModel; // opaque type outside refresh
// most recent data
vec3_t axis[3]; // rotation vectors
qboolean nonNormalizedAxes; // axis are not normalized, i.e. they have scale
vec3_t origin; // also used as MODEL_BEAM's "from"
// previous data for frame interpolation
vec3_t oldorigin; // also used as MODEL_BEAM's "to"
// texturing
qhandle_t customShader; // use one image for the entire thing
// misc
byte shaderRGBA[4]; // colors used by rgbgen entity shaders
vec2_t shaderTexCoord; // texture coordinates used by tcMod entity modifiers
// extra sprite information
float radius;
float rotation;
// misc
float shaderTime; // subtracted from refdef time to control effect start times
int frame; // also used as MODEL_BEAM's diameter
//
//
// end miniRefEntity_t
//
//
// specific full refEntity_t data
//
//
// most recent data
vec3_t lightingOrigin; // so multi-part models can be lit identically (RF_LIGHTING_ORIGIN)
float shadowPlane; // projection shadows go here, stencils go slightly lower
// previous data for frame interpolation
int oldframe;
float backlerp; // 0.0 = current, 1.0 = old
// texturing
int skinNum; // inline skin index
qhandle_t customSkin; // NULL for default skin
// texturing
union
{
// int skinNum; // inline skin index
// ivec3_t terxelCoords; // coords of patch for RT_TERXELS
struct
{
int miniStart;
int miniCount;
} uMini;
} uRefEnt;
// extra sprite information
union {
struct
{
float rotation;
float radius;
byte vertRGBA[4][4];
} sprite;
struct
{
float width;
float width2;
float stscale;
} line;
struct // that whole put-the-opening-brace-on-the-same-line-as-the-beginning-of-the-definition coding style is fecal
{
float width;
vec3_t control1;
vec3_t control2;
} bezier;
struct
{
float width;
float width2;
float stscale;
float height;
float bias;
qboolean wrap;
} cylinder;
struct
{
float width;
float deviation;
float stscale;
qboolean wrap;
qboolean taper;
} electricity;
} data;
vec3_t angles; // rotation angles - used for Ghoul2
vec3_t modelScale; // axis scale for models
void *ghoul2; // has to be at the end of the ref-ent in order for it to be created properly
} refEntity_t;
#define MAX_RENDER_STRINGS 8
#define MAX_RENDER_STRING_LENGTH 32
typedef struct {
int x, y, width, height;
float fov_x, fov_y;
vec3_t vieworg;
vec3_t viewaxis[3]; // transformation matrix
// time in milliseconds for shader effects and other time dependent rendering issues
int time;
int rdflags; // RDF_NOWORLDMODEL, etc
// 1 bits will prevent the associated area from rendering at all
byte areamask[MAX_MAP_AREA_BYTES];
// text messages for deform text shaders
char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
vec3_t viewangles;
} refdef_t;
typedef enum {
STEREO_CENTER,
STEREO_LEFT,
STEREO_RIGHT
} stereoFrame_t;
/*
** glconfig_t
**
** Contains variables specific to the OpenGL configuration
** being run right now. These are constant once the OpenGL
** subsystem is initialized.
*/
typedef enum {
GLDRV_ICD, // driver is integrated with window system
// WARNING: there are tests that check for
// > GLDRV_ICD for minidriverness, so this
// should always be the lowest value in this
// enum set
GLDRV_STANDALONE, // driver is a non-3Dfx standalone driver
GLDRV_VOODOO // driver is a 3Dfx standalone driver
} glDriverType_t;
typedef enum {
GLHW_GENERIC, // where everthing works the way it should
GLHW_3DFX_2D3D, // Voodoo Banshee or Voodoo3, relevant since if this is
// the hardware type then there can NOT exist a secondary
// display adapter
GLHW_RIVA128, // where you can't interpolate alpha
GLHW_RAGEPRO, // where you can't modulate alpha on alpha textures
GLHW_PERMEDIA2 // where you don't have src*dst
} glHardwareType_t;
typedef struct {
char renderer_string[MAX_STRING_CHARS];
char vendor_string[MAX_STRING_CHARS];
char version_string[MAX_STRING_CHARS];
char extensions_string[BIG_INFO_STRING];
int maxTextureSize; // queried from GL
int maxActiveTextures; // multitexture ability
int tfSolidCompressed;
float tfSolidCompressedBPT;
int tfAlphaCompressed;
float tfAlphaCompressedBPT;
int tfSolidUncompressed;
float tfSolidUncompressedBPT;
int tfAlphaUncompressed;
float tfAlphaUncompressedBPT;
int tfLightmap;
float tfLightmapBPT;
int tfCinematic; // Specially for the Voodoo4 - glTexImage2D can only handle 16 bit
float tfCinematicBPT;
int colorBits, depthBits, stencilBits;
glDriverType_t driverType;
glHardwareType_t hardwareType;
qboolean deviceSupportsGamma;
qboolean textureEnvAddAvailable;
qboolean textureFilterAnisotropicAvailable;
qboolean clampToEdgeAvailable;
int vidWidth, vidHeight;
// aspect is the screen's physical width / height, which may be different
// than scrWidth / scrHeight if the pixels are non-square
// normal screens should be 4/3, but wide aspect monitors may be 16/9
float windowAspect;
int displayFrequency;
// synonymous with "does rendering consume the entire screen?", therefore
// a Voodoo or Voodoo2 will have this set to TRUE, as will a Win32 ICD that
// used CDS.
qboolean isFullscreen;
qboolean stereoEnabled;
qboolean smpActive; // dual processor
} glconfig_t;
typedef enum
{
VO_NONE = 0,
VO_NIGHTVISION, // parm1 = visible distance, parm2 = not used
VO_INFRARED, // parm1 = distance to see heat, parm2 = distance you can see them through walls
} visual_t;
#if !defined _WIN32
#define _3DFX_DRIVER_NAME "libMesaVoodooGL.so"
#define OPENGL_DRIVER_NAME "libGL.so"
#else
#define _3DFX_DRIVER_NAME "3dfxvgl"
#define OPENGL_DRIVER_NAME "opengl32"
#endif // !defined _WIN32
#endif // __TR_TYPES_H

5511
code/game/ai_main.c Normal file

File diff suppressed because it is too large Load Diff

363
code/game/ai_main.h Normal file
View File

@ -0,0 +1,363 @@
#define DEFAULT_FORCEPOWERS "5-1-000000000000000000"
#define MAX_CHAT_BUFFER_SIZE 65536
#define MAX_CHAT_LINE_SIZE 128
#define MAX_WPARRAY_SIZE 4096
#define MAX_NEIGHBOR_SIZE 32
#define MAX_NEIGHBOR_LINK_DISTANCE 128
#define MAX_NEIGHBOR_FORCEJUMP_LINK_DISTANCE 400
#define TABLE_BRANCH_DISTANCE 32
#define MAX_NODETABLE_SIZE 4096
#define MAX_LOVED_ONES 4
#define MAX_ATTACHMENT_NAME 64
#define MAX_FORCE_INFO_SIZE 2048
#define WPFLAG_JUMP 0x00000010 //jump when we hit this
#define WPFLAG_DUCK 0x00000020 //duck while moving around here
#define WPFLAG_NOVIS 0x00000400 //go here for a bit even with no visibility
#define WPFLAG_SNIPEORCAMPSTAND 0x00000800 //a good position to snipe or camp - stand
#define WPFLAG_WAITFORFUNC 0x00001000 //wait for a func brushent under this point before moving here
#define WPFLAG_SNIPEORCAMP 0x00002000 //a good position to snipe or camp - crouch
#define WPFLAG_ONEWAY_FWD 0x00004000 //can only go forward on the trial from here (e.g. went over a ledge)
#define WPFLAG_ONEWAY_BACK 0x00008000 //can only go backward on the trail from here
#define WPFLAG_GOALPOINT 0x00010000 //make it a goal to get here.. goal points will be decided by setting "weight" values
#define WPFLAG_RED_FLAG 0x00020000 //red flag
#define WPFLAG_BLUE_FLAG 0x00040000 //blue flag
#define WPFLAG_NOMOVEFUNC 0x00200000 //don't move over if a func is under
#define WP_KEEP_FLAG_DIST 128
#define BWEAPONRANGE_MELEE 1
#define BWEAPONRANGE_MID 2
#define BWEAPONRANGE_LONG 3
#define BWEAPONRANGE_SABER 4
#define MELEE_ATTACK_RANGE 256
#define SABER_ATTACK_RANGE 128
#define MAX_CHICKENWUSS_TIME 10000 //wait 10 secs between checking which run-away path to take
#define BOT_RUN_HEALTH 40
#define BOT_WPTOUCH_DISTANCE 32
#define ENEMY_FORGET_MS 10000
//if our enemy isn't visible within 10000ms (aprx 10sec) then "forget" about him and treat him like every other threat, but still look for
//more immediate threats while main enemy is not visible
#define BOT_PLANT_DISTANCE 256 //plant if within this radius from the last spotted enemy position
#define BOT_PLANT_INTERVAL 15000 //only plant once per 15 seconds at max
#define BOT_PLANT_BLOW_DISTANCE 256 //blow det packs if enemy is within this radius and I am further away than the enemy
#define BOT_MAX_WEAPON_GATHER_TIME 1000 //spend a max of 1 second after spawn issuing orders to gather weapons before attacking enemy base
#define BOT_MAX_WEAPON_CHASE_TIME 15000 //time to spend gathering the weapon before persuing the enemy base (in case it takes longer than expected)
#define BOT_MAX_WEAPON_CHASE_CTF 5000 //time to spend gathering the weapon before persuing the enemy base (in case it takes longer than expected) [ctf-only]
#define BOT_MIN_SAGA_GOAL_SHOOT 1024
#define BOT_MIN_SAGA_GOAL_TRAVEL 128
#define BASE_GUARD_DISTANCE 256 //guarding the flag
#define BASE_FLAGWAIT_DISTANCE 256 //has the enemy flag and is waiting in his own base for his flag to be returned
#define BASE_GETENEMYFLAG_DISTANCE 256 //waiting around to get the enemy's flag
#define BOT_FLAG_GET_DISTANCE 256
#define MAX_PROJECTILE_DISTANCE 256
typedef enum
{
CTFSTATE_NONE,
CTFSTATE_ATTACKER,
CTFSTATE_DEFENDER,
CTFSTATE_RETRIEVAL,
CTFSTATE_GUARDCARRIER,
CTFSTATE_GETFLAGHOME,
CTFSTATE_MAXCTFSTATES
} bot_ctf_state_t;
typedef enum
{
SAGASTATE_NONE,
SAGASTATE_ATTACKER,
SAGASTATE_DEFENDER,
SAGASTATE_MAXSAGASTATES
} bot_saga_state_t;
typedef enum
{
TEAMPLAYSTATE_NONE,
TEAMPLAYSTATE_FOLLOWING,
TEAMPLAYSTATE_ASSISTING,
TEAMPLAYSTATE_REGROUP,
TEAMPLAYSTATE_MAXTPSTATES
} bot_teamplay_state_t;
typedef struct wpneighbor_s
{
int num;
int forceJumpTo;
} wpneighbor_t;
typedef struct wpobject_s
{
vec3_t origin;
int inuse;
int index;
float weight;
float disttonext;
int flags;
int associated_entity;
int forceJumpTo;
int neighbornum;
//int neighbors[MAX_NEIGHBOR_SIZE];
wpneighbor_t neighbors[MAX_NEIGHBOR_SIZE];
} wpobject_t;
typedef struct botattachment_s
{
int level;
char name[MAX_ATTACHMENT_NAME];
} botattachment_t;
typedef struct nodeobject_s
{
vec3_t origin;
int inuse;
int index;
float weight;
int flags;
int neighbornum;
} nodeobject_t;
typedef struct boteventtracker_s
{
int eventSequence;
int events[MAX_PS_EVENTS];
float eventTime;
} boteventtracker_t;
typedef struct botskills_s
{
int reflex;
float accuracy;
float turnspeed;
float turnspeed_combat;
float maxturn;
int perfectaim;
} botskills_t;
//bot state
typedef struct bot_state_s
{
int inuse; //true if this state is used by a bot client
int botthink_residual; //residual for the bot thinks
int client; //client number of the bot
int entitynum; //entity number of the bot
playerState_t cur_ps; //current player state
usercmd_t lastucmd; //usercmd from last frame
bot_settings_t settings; //several bot settings
float thinktime; //time the bot thinks this frame
vec3_t origin; //origin of the bot
vec3_t velocity; //velocity of the bot
vec3_t eye; //eye coordinates of the bot
int setupcount; //true when the bot has just been setup
float ltime; //local bot time
float entergame_time; //time the bot entered the game
int ms; //move state of the bot
int gs; //goal state of the bot
int ws; //weapon state of the bot
vec3_t viewangles; //current view angles
vec3_t ideal_viewangles; //ideal view angles
vec3_t viewanglespeed;
//rww - new AI values
gentity_t *currentEnemy;
gentity_t *revengeEnemy;
gentity_t *squadLeader;
gentity_t *lastHurt;
gentity_t *lastAttacked;
gentity_t *wantFlag;
gentity_t *touchGoal;
gentity_t *shootGoal;
gentity_t *dangerousObject;
vec3_t staticFlagSpot;
int revengeHateLevel;
int isSquadLeader;
int squadRegroupInterval;
int squadCannotLead;
int lastDeadTime;
wpobject_t *wpCurrent;
wpobject_t *wpDestination;
wpobject_t *wpStoreDest;
vec3_t goalAngles;
vec3_t goalMovedir;
vec3_t goalPosition;
vec3_t lastEnemySpotted;
vec3_t hereWhenSpotted;
int lastVisibleEnemyIndex;
int hitSpotted;
int wpDirection;
float destinationGrabTime;
float wpSeenTime;
float wpTravelTime;
float wpDestSwitchTime;
float wpSwitchTime;
float wpDestIgnoreTime;
float timeToReact;
float enemySeenTime;
float chickenWussCalculationTime;
float beStill;
float duckTime;
float jumpTime;
float jDelay;
float aimOffsetTime;
float aimOffsetAmtYaw;
float aimOffsetAmtPitch;
float frame_Waypoint_Len;
int frame_Waypoint_Vis;
float frame_Enemy_Len;
int frame_Enemy_Vis;
int isCamper;
float isCamping;
wpobject_t *wpCamping;
wpobject_t *wpCampingTo;
qboolean campStanding;
int randomNavTime;
int randomNav;
int meleeSpecialist;
int canChat;
int chatFrequency;
char currentChat[MAX_CHAT_LINE_SIZE];
float chatTime;
float chatTime_stored;
int doChat;
int chatTeam;
gentity_t *chatObject;
gentity_t *chatAltObject;
float meleeStrafeTime;
int meleeStrafeDir;
float meleeStrafeDisable;
int altChargeTime;
float escapeDirTime;
float dontGoBack;
int doAttack;
int doAltAttack;
int forceWeaponSelect;
int virtualWeapon;
int runningLikeASissy;
int runningToEscapeThreat;
//char chatBuffer[MAX_CHAT_BUFFER_SIZE];
//Since we're once again not allocating bot structs dynamically,
//shoving a 64k chat buffer into one is a bad thing.
botskills_t skills;
botattachment_t loved[MAX_LOVED_ONES];
int lovednum;
int loved_death_thresh;
int deathActivitiesDone;
float botWeaponWeights[WP_NUM_WEAPONS];
int ctfState;
int teamplayState;
int state_Forced; //set by player ordering menu
int noUseTime;
vec3_t launchAngle;
//end rww
} bot_state_t;
void *B_TempAlloc(int size);
void B_TempFree(int size);
void *B_Alloc(int size);
void B_Free(void *ptr);
//resets the whole bot state
void BotResetState(bot_state_t *bs);
//returns the number of bots in the game
int NumBots(void);
void BotUtilizePersonality(bot_state_t *bs);
int BotDoChat(bot_state_t *bs, char *section, int always);
void StandardBotAI(bot_state_t *bs, float thinktime);
void BotWaypointRender(void);
int OrgVisibleBox(vec3_t org1, vec3_t mins, vec3_t maxs, vec3_t org2, int ignore);
int BotIsAChickenWuss(bot_state_t *bs);
int GetNearestVisibleWP(vec3_t org, int ignore);
int GetBestIdleGoal(bot_state_t *bs);
char *ConcatArgs( int start );
extern vmCvar_t bot_attachments;
extern vmCvar_t bot_camp;
extern vmCvar_t bot_wp_info;
extern vmCvar_t bot_wp_edit;
extern vmCvar_t bot_wp_clearweight;
extern vmCvar_t bot_wp_distconnect;
extern vmCvar_t bot_wp_visconnect;
extern wpobject_t *flagRed;
extern wpobject_t *oFlagRed;
extern wpobject_t *flagBlue;
extern wpobject_t *oFlagBlue;
extern gentity_t *eFlagRed;
extern gentity_t *eFlagBlue;
extern char gBotChatBuffer[MAX_CLIENTS][MAX_CHAT_BUFFER_SIZE];
extern float gWPRenderTime;
extern float gDeactivated;
extern float gBotEdit;
extern int gWPRenderedFrame;
extern wpobject_t *gWPArray[MAX_WPARRAY_SIZE];
extern int gWPNum;
extern int gLastPrintedIndex;
extern nodeobject_t nodetable[MAX_NODETABLE_SIZE];
extern int nodenum;
extern float floattime;
#define FloatTime() floattime

799
code/game/ai_util.c Normal file
View File

@ -0,0 +1,799 @@
// Copyright (C) 2001-2002 Raven Software.
//
// ai_util.c
#include "g_local.h"
#include "q_shared.h"
#include "botlib.h"
#include "ai_main.h"
#ifdef BOT_ZMALLOC
#define MAX_BALLOC 8192
void *BAllocList[MAX_BALLOC];
#endif
char gBotChatBuffer[MAX_CLIENTS][MAX_CHAT_BUFFER_SIZE];
//A total of 4194304 bytes. Not very nice at all, but we really
//want to have at least 65k for the total chat buffer just in
//case and we have no method of dynamic allocation here.
void *B_TempAlloc(int size)
{
return trap_VM_LocalTempAlloc(size);
}
void B_TempFree(int size)
{
trap_VM_LocalTempFree(size);
}
void *B_Alloc(int size)
{
#ifdef BOT_ZMALLOC
void *ptr = NULL;
int i = 0;
#ifdef BOTMEMTRACK
int free = 0;
int used = 0;
while (i < MAX_BALLOC)
{
if (!BAllocList[i])
{
free++;
}
else
{
used++;
}
i++;
}
Com_Printf("Allocations used: %i\nFree allocation slots: %i\n", used, free);
i = 0;
#endif
ptr = trap_BotGetMemoryGame(size);
while (i < MAX_BALLOC)
{
if (!BAllocList[i])
{
BAllocList[i] = ptr;
break;
}
i++;
}
if (i == MAX_BALLOC)
{
//If this happens we'll have to rely on this chunk being freed manually with B_Free, which it hopefully will be
#ifdef DEBUG
Com_Printf("WARNING: MAXIMUM B_ALLOC ALLOCATIONS EXCEEDED\n");
#endif
}
return ptr;
#else
return trap_VM_LocalAlloc(size);
#endif
}
void B_Free(void *ptr)
{
#ifdef BOT_ZMALLOC
int i = 0;
#ifdef BOTMEMTRACK
int free = 0;
int used = 0;
while (i < MAX_BALLOC)
{
if (!BAllocList[i])
{
free++;
}
else
{
used++;
}
i++;
}
Com_Printf("Allocations used: %i\nFree allocation slots: %i\n", used, free);
i = 0;
#endif
while (i < MAX_BALLOC)
{
if (BAllocList[i] == ptr)
{
BAllocList[i] = NULL;
break;
}
i++;
}
if (i == MAX_BALLOC)
{
//Likely because the limit was exceeded and we're now freeing the chunk manually as we hoped would happen
#ifdef DEBUG
Com_Printf("WARNING: Freeing allocation which is not in the allocation structure\n");
#endif
}
trap_BotFreeMemoryGame(ptr);
#endif
}
void B_InitAlloc(void)
{
#ifdef BOT_ZMALLOC
memset(BAllocList, 0, sizeof(BAllocList));
#endif
memset(gWPArray, 0, sizeof(gWPArray));
}
void B_CleanupAlloc(void)
{
#ifdef BOT_ZMALLOC
int i = 0;
while (i < MAX_BALLOC)
{
if (BAllocList[i])
{
trap_BotFreeMemoryGame(BAllocList[i]);
BAllocList[i] = NULL;
}
i++;
}
#endif
}
int GetValueGroup(char *buf, char *group, char *outbuf)
{
char *place, *placesecond;
int iplace;
int failure;
int i;
int startpoint, startletter;
int subg = 0;
i = 0;
iplace = 0;
place = strstr(buf, group);
if (!place)
{
return 0;
}
startpoint = place - buf + strlen(group) + 1;
startletter = (place - buf) - 1;
failure = 0;
while (buf[startpoint+1] != '{' || buf[startletter] != '\n')
{
placesecond = strstr(place+1, group);
if (placesecond)
{
startpoint += (placesecond - place);
startletter += (placesecond - place);
place = placesecond;
}
else
{
failure = 1;
break;
}
}
if (failure)
{
return 0;
}
//we have found the proper group name if we made it here, so find the opening brace and read into the outbuf
//until hitting the end brace
while (buf[startpoint] != '{')
{
startpoint++;
}
startpoint++;
while (buf[startpoint] != '}' || subg)
{
if (buf[startpoint] == '{')
{
subg++;
}
else if (buf[startpoint] == '}')
{
subg--;
}
outbuf[i] = buf[startpoint];
i++;
startpoint++;
}
outbuf[i] = '\0';
return 1;
}
int GetPairedValue(char *buf, char *key, char *outbuf)
{
char *place, *placesecond;
int startpoint, startletter;
int i, found;
if (!buf || !key || !outbuf)
{
return 0;
}
i = 0;
while (buf[i] && buf[i] != '\0')
{
if (buf[i] == '/')
{
if (buf[i+1] && buf[i+1] != '\0' && buf[i+1] == '/')
{
while (buf[i] != '\n')
{
buf[i] = '/';
i++;
}
}
}
i++;
}
place = strstr(buf, key);
if (!place)
{
return 0;
}
//tab == 9
startpoint = place - buf + strlen(key);
startletter = (place - buf) - 1;
found = 0;
while (!found)
{
if (startletter == 0 || !buf[startletter] || buf[startletter] == '\0' || buf[startletter] == 9 || buf[startletter] == ' ' || buf[startletter] == '\n')
{
if (buf[startpoint] == '\0' || buf[startpoint] == 9 || buf[startpoint] == ' ' || buf[startpoint] == '\n')
{
found = 1;
break;
}
}
placesecond = strstr(place+1, key);
if (placesecond)
{
startpoint += placesecond - place;
startletter += placesecond - place;
place = placesecond;
}
else
{
place = NULL;
break;
}
}
if (!found || !place || !buf[startpoint] || buf[startpoint] == '\0')
{
return 0;
}
while (buf[startpoint] == ' ' || buf[startpoint] == 9 || buf[startpoint] == '\n')
{
startpoint++;
}
i = 0;
while (buf[startpoint] && buf[startpoint] != '\0' && buf[startpoint] != '\n')
{
outbuf[i] = buf[startpoint];
i++;
startpoint++;
}
outbuf[i] = '\0';
return 1;
}
int BotDoChat(bot_state_t *bs, char *section, int always)
{
char *chatgroup;
int rVal;
int inc_1;
int inc_2;
int inc_n;
int lines;
int checkedline;
int getthisline;
gentity_t *cobject;
if (!bs->canChat)
{
return 0;
}
if (bs->doChat)
{ //already have a chat scheduled
return 0;
}
if (Q_irand(1, 10) > bs->chatFrequency && !always)
{
return 0;
}
bs->chatTeam = 0;
chatgroup = (char *)B_TempAlloc(MAX_CHAT_BUFFER_SIZE);
rVal = GetValueGroup(gBotChatBuffer[bs->client], section, chatgroup);
if (!rVal) //the bot has no group defined for the specified chat event
{
B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
return 0;
}
inc_1 = 0;
inc_2 = 2;
while (chatgroup[inc_2] && chatgroup[inc_2] != '\0')
{
if (chatgroup[inc_2] != 13 && chatgroup[inc_2] != 9)
{
chatgroup[inc_1] = chatgroup[inc_2];
inc_1++;
}
inc_2++;
}
chatgroup[inc_1] = '\0';
inc_1 = 0;
lines = 0;
while (chatgroup[inc_1] && chatgroup[inc_1] != '\0')
{
if (chatgroup[inc_1] == '\n')
{
lines++;
}
inc_1++;
}
if (!lines)
{
B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
return 0;
}
getthisline = Q_irand(0, (lines+1));
if (getthisline < 1)
{
getthisline = 1;
}
if (getthisline > lines)
{
getthisline = lines;
}
checkedline = 1;
inc_1 = 0;
while (checkedline != getthisline)
{
if (chatgroup[inc_1] && chatgroup[inc_1] != '\0')
{
if (chatgroup[inc_1] == '\n')
{
inc_1++;
checkedline++;
}
}
if (checkedline == getthisline)
{
break;
}
inc_1++;
}
//we're at the starting position of the desired line here
inc_2 = 0;
while (chatgroup[inc_1] != '\n')
{
chatgroup[inc_2] = chatgroup[inc_1];
inc_2++;
inc_1++;
}
chatgroup[inc_2] = '\0';
//trap_EA_Say(bs->client, chatgroup);
inc_1 = 0;
inc_2 = 0;
if (strlen(chatgroup) > MAX_CHAT_LINE_SIZE)
{
B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
return 0;
}
while (chatgroup[inc_1])
{
if (chatgroup[inc_1] == '%' && chatgroup[inc_1+1] != '%')
{
inc_1++;
if (chatgroup[inc_1] == 's' && bs->chatObject)
{
cobject = bs->chatObject;
}
else if (chatgroup[inc_1] == 'a' && bs->chatAltObject)
{
cobject = bs->chatAltObject;
}
else
{
cobject = NULL;
}
if (cobject && cobject->client)
{
inc_n = 0;
while (cobject->client->pers.netname[inc_n])
{
bs->currentChat[inc_2] = cobject->client->pers.netname[inc_n];
inc_2++;
inc_n++;
}
inc_2--; //to make up for the auto-increment below
}
}
else
{
bs->currentChat[inc_2] = chatgroup[inc_1];
}
inc_2++;
inc_1++;
}
bs->currentChat[inc_2] = '\0';
if (strcmp(section, "GeneralGreetings") == 0)
{
bs->doChat = 2;
}
else
{
bs->doChat = 1;
}
bs->chatTime_stored = (strlen(bs->currentChat)*45)+Q_irand(1300, 1500);
bs->chatTime = level.time + bs->chatTime_stored;
B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
return 1;
}
void ParseEmotionalAttachments(bot_state_t *bs, char *buf)
{
int i = 0;
int i_c = 0;
char tbuf[16];
while (buf[i] && buf[i] != '}')
{
while (buf[i] == ' ' || buf[i] == '{' || buf[i] == 9 || buf[i] == 13 || buf[i] == '\n')
{
i++;
}
if (buf[i] && buf[i] != '}')
{
i_c = 0;
while (buf[i] != '{' && buf[i] != 9 && buf[i] != 13 && buf[i] != '\n')
{
bs->loved[bs->lovednum].name[i_c] = buf[i];
i_c++;
i++;
}
bs->loved[bs->lovednum].name[i_c] = '\0';
while (buf[i] == ' ' || buf[i] == '{' || buf[i] == 9 || buf[i] == 13 || buf[i] == '\n')
{
i++;
}
i_c = 0;
while (buf[i] != '{' && buf[i] != 9 && buf[i] != 13 && buf[i] != '\n')
{
tbuf[i_c] = buf[i];
i_c++;
i++;
}
tbuf[i_c] = '\0';
bs->loved[bs->lovednum].level = atoi(tbuf);
bs->lovednum++;
}
else
{
break;
}
if (bs->lovednum >= MAX_LOVED_ONES)
{
return;
}
i++;
}
}
int ReadChatGroups(bot_state_t *bs, char *buf)
{
char *cgroupbegin;
int cgbplace;
int i;
cgroupbegin = strstr(buf, "BEGIN_CHAT_GROUPS");
if (!cgroupbegin)
{
return 0;
}
if (strlen(cgroupbegin) >= MAX_CHAT_BUFFER_SIZE)
{
Com_Printf(S_COLOR_RED "Error: Personality chat section exceeds max size\n");
return 0;
}
cgbplace = cgroupbegin - buf+1;
while (buf[cgbplace] != '\n')
{
cgbplace++;
}
i = 0;
while (buf[cgbplace] && buf[cgbplace] != '\0')
{
gBotChatBuffer[bs->client][i] = buf[cgbplace];
i++;
cgbplace++;
}
gBotChatBuffer[bs->client][i] = '\0';
return 1;
}
char personalityBuffer[131072];
void BotUtilizePersonality(bot_state_t *bs)
{
fileHandle_t f;
int len, rlen;
int failed;
int i;
char *readbuf, *group;
len = trap_FS_FOpenFile(bs->settings.personalityfile, &f, FS_READ);
failed = 0;
if (!f)
{
Com_Printf(S_COLOR_RED "Error: Specified personality not found\n");
return;
}
if (len >= 131072)
{
Com_Printf(S_COLOR_RED "Personality file exceeds maximum length\n");
return;
}
trap_FS_Read(personalityBuffer, len, f);
rlen = len;
while (len < 131072)
{ //kill all characters after the file length, since sometimes FS_Read doesn't do that entirely (or so it seems)
personalityBuffer[len] = '\0';
len++;
}
len = rlen;
readbuf = (char *)trap_VM_LocalTempAlloc(1024);
group = (char *)trap_VM_LocalTempAlloc(65536);
if (!GetValueGroup(personalityBuffer, "GeneralBotInfo", group))
{
Com_Printf(S_COLOR_RED "Personality file contains no GeneralBotInfo group\n");
failed = 1; //set failed so we know to set everything to default values
}
if (!failed && GetPairedValue(group, "reflex", readbuf))
{
bs->skills.reflex = atoi(readbuf);
}
else
{
bs->skills.reflex = 100; //default
}
if (!failed && GetPairedValue(group, "accuracy", readbuf))
{
bs->skills.accuracy = atof(readbuf);
}
else
{
bs->skills.accuracy = 10; //default
}
if (!failed && GetPairedValue(group, "turnspeed", readbuf))
{
bs->skills.turnspeed = atof(readbuf);
}
else
{
bs->skills.turnspeed = 0.01f; //default
}
if (!failed && GetPairedValue(group, "turnspeed_combat", readbuf))
{
bs->skills.turnspeed_combat = atof(readbuf);
}
else
{
bs->skills.turnspeed_combat = 0.05f; //default
}
if (!failed && GetPairedValue(group, "maxturn", readbuf))
{
bs->skills.maxturn = atof(readbuf);
}
else
{
bs->skills.maxturn = 360; //default
}
if (!failed && GetPairedValue(group, "perfectaim", readbuf))
{
bs->skills.perfectaim = atoi(readbuf);
}
else
{
bs->skills.perfectaim = 0; //default
}
if (!failed && GetPairedValue(group, "chatability", readbuf))
{
bs->canChat = atoi(readbuf);
}
else
{
bs->canChat = 0; //default
}
if (!failed && GetPairedValue(group, "chatfrequency", readbuf))
{
bs->chatFrequency = atoi(readbuf);
}
else
{
bs->chatFrequency = 5; //default
}
if (!failed && GetPairedValue(group, "hatelevel", readbuf))
{
bs->loved_death_thresh = atoi(readbuf);
}
else
{
bs->loved_death_thresh = 3; //default
}
if (!failed && GetPairedValue(group, "camper", readbuf))
{
bs->isCamper = atoi(readbuf);
}
else
{
bs->isCamper = 0; //default
}
if (!failed && GetPairedValue(group, "meleeSpecialist", readbuf))
{
bs->meleeSpecialist = atoi(readbuf);
}
else
{
bs->meleeSpecialist = 0; //default
}
i = 0;
while (i < MAX_CHAT_BUFFER_SIZE)
{ //clear out the chat buffer for this bot
gBotChatBuffer[bs->client][i] = '\0';
i++;
}
if (bs->canChat)
{
if (!ReadChatGroups(bs, personalityBuffer))
{
bs->canChat = 0;
}
}
if (GetValueGroup(personalityBuffer, "BotWeaponWeights", group))
{
for (i=0; i < WP_NUM_WEAPONS; i++)
{
if (GetPairedValue(group, bg_weaponNames[i], readbuf))
{
bs->botWeaponWeights[i] = atoi(readbuf);
}
}
}
bs->lovednum = 0;
if (GetValueGroup(personalityBuffer, "EmotionalAttachments", group))
{
ParseEmotionalAttachments(bs, group);
}
trap_VM_LocalTempFree(65536);
trap_VM_LocalTempFree(1024);
trap_FS_FCloseFile(f);
}

2341
code/game/ai_wpnav.c Normal file

File diff suppressed because it is too large Load Diff

0
code/game/anims.h Normal file
View File

205
code/game/be_aas.h Normal file
View File

@ -0,0 +1,205 @@
// Copyright (C) 2001-2002 Raven Software
//
/*****************************************************************************
* name: be_aas.h
*
* desc: Area Awareness System, stuff exported to the AI
*
* $Archive: /source/code/botlib/be_aas.h $
* $Author: Mrelusive $
* $Revision: 2 $
* $Modtime: 10/05/99 3:32p $
* $Date: 10/05/99 3:42p $
*
*****************************************************************************/
#ifndef MAX_STRINGFIELD
#define MAX_STRINGFIELD 80
#endif
//travel flags
#define TFL_INVALID 0x00000001 //traveling temporary not possible
#define TFL_WALK 0x00000002 //walking
#define TFL_CROUCH 0x00000004 //crouching
#define TFL_BARRIERJUMP 0x00000008 //jumping onto a barrier
#define TFL_JUMP 0x00000010 //jumping
#define TFL_LADDER 0x00000020 //climbing a ladder
#define TFL_WALKOFFLEDGE 0x00000080 //walking of a ledge
#define TFL_SWIM 0x00000100 //swimming
#define TFL_WATERJUMP 0x00000200 //jumping out of the water
#define TFL_TELEPORT 0x00000400 //teleporting
#define TFL_ELEVATOR 0x00000800 //elevator
#define TFL_ROCKETJUMP 0x00001000 //rocket jumping
#define TFL_BFGJUMP 0x00002000 //bfg jumping
#define TFL_GRAPPLEHOOK 0x00004000 //grappling hook
#define TFL_DOUBLEJUMP 0x00008000 //double jump
#define TFL_RAMPJUMP 0x00010000 //ramp jump
#define TFL_STRAFEJUMP 0x00020000 //strafe jump
#define TFL_JUMPPAD 0x00040000 //jump pad
#define TFL_AIR 0x00080000 //travel through air
#define TFL_WATER 0x00100000 //travel through water
#define TFL_SLIME 0x00200000 //travel through slime
#define TFL_LAVA 0x00400000 //travel through lava
#define TFL_DONOTENTER 0x00800000 //travel through donotenter area
#define TFL_FUNCBOB 0x01000000 //func bobbing
#define TFL_FLIGHT 0x02000000 //flight
#define TFL_BRIDGE 0x04000000 //move over a bridge
//
#define TFL_NOTTEAM1 0x08000000 //not team 1
#define TFL_NOTTEAM2 0x10000000 //not team 2
//default travel flags
#define TFL_DEFAULT TFL_WALK|TFL_CROUCH|TFL_BARRIERJUMP|\
TFL_JUMP|TFL_LADDER|\
TFL_WALKOFFLEDGE|TFL_SWIM|TFL_WATERJUMP|\
TFL_TELEPORT|TFL_ELEVATOR|\
TFL_AIR|TFL_WATER|TFL_JUMPPAD|TFL_FUNCBOB
typedef enum
{
SOLID_NOT, // no interaction with other objects
SOLID_TRIGGER, // only touch when inside, after moving
SOLID_BBOX, // touch on edge
SOLID_BSP // bsp clip, touch on edge
} solid_t;
//a trace is returned when a box is swept through the AAS world
typedef struct aas_trace_s
{
qboolean startsolid; // if true, the initial point was in a solid area
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
int ent; // entity blocking the trace
int lastarea; // last area the trace was in (zero if none)
int area; // area blocking the trace (zero if none)
int planenum; // number of the plane that was hit
} aas_trace_t;
/* Defined in botlib.h
//bsp_trace_t hit surface
typedef struct bsp_surface_s
{
char name[16];
int flags;
int value;
} bsp_surface_t;
//a trace is returned when a box is swept through the BSP world
typedef struct bsp_trace_s
{
qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
cplane_t plane; // surface normal at impact
float exp_dist; // expanded plane distance
int sidenum; // number of the brush side hit
bsp_surface_t surface; // hit surface
int contents; // contents on other side of surface hit
int ent; // number of entity hit
} bsp_trace_t;
//
*/
//entity info
typedef struct aas_entityinfo_s
{
int valid; // true if updated this frame
int type; // entity type
int flags; // entity flags
float ltime; // local time
float update_time; // time between last and current update
int number; // number of the entity
vec3_t origin; // origin of the entity
vec3_t angles; // angles of the model
vec3_t old_origin; // for lerping
vec3_t lastvisorigin; // last visible origin
vec3_t mins; // bounding box minimums
vec3_t maxs; // bounding box maximums
int groundent; // ground entity
int solid; // solid type
int modelindex; // model used
int modelindex2; // weapons, CTF flags, etc
int frame; // model frame number
int event; // impulse events -- muzzle flashes, footsteps, etc
int eventParm; // even parameter
int gametypeitems; // bit flags
int weapon; // determines weapon and flash model, etc
int legsAnim; // mask off ANIM_TOGGLEBIT
int torsoAnim; // mask off ANIM_TOGGLEBIT
} aas_entityinfo_t;
// area info
typedef struct aas_areainfo_s
{
int contents;
int flags;
int presencetype;
int cluster;
vec3_t mins;
vec3_t maxs;
vec3_t center;
} aas_areainfo_t;
// client movement prediction stop events, stop as soon as:
#define SE_NONE 0
#define SE_HITGROUND 1 // the ground is hit
#define SE_LEAVEGROUND 2 // there's no ground
#define SE_ENTERWATER 4 // water is entered
#define SE_ENTERSLIME 8 // slime is entered
#define SE_ENTERLAVA 16 // lava is entered
#define SE_HITGROUNDDAMAGE 32 // the ground is hit with damage
#define SE_GAP 64 // there's a gap
#define SE_TOUCHJUMPPAD 128 // touching a jump pad area
#define SE_TOUCHTELEPORTER 256 // touching teleporter
#define SE_ENTERAREA 512 // the given stoparea is entered
#define SE_HITGROUNDAREA 1024 // a ground face in the area is hit
#define SE_HITBOUNDINGBOX 2048 // hit the specified bounding box
#define SE_TOUCHCLUSTERPORTAL 4096 // touching a cluster portal
typedef struct aas_clientmove_s
{
vec3_t endpos; //position at the end of movement prediction
int endarea; //area at end of movement prediction
vec3_t velocity; //velocity at the end of movement prediction
aas_trace_t trace; //last trace
int presencetype; //presence type at end of movement prediction
int stopevent; //event that made the prediction stop
int endcontents; //contents at the end of movement prediction
float time; //time predicted ahead
int frames; //number of frames predicted ahead
} aas_clientmove_t;
// alternate route goals
#define ALTROUTEGOAL_ALL 1
#define ALTROUTEGOAL_CLUSTERPORTALS 2
#define ALTROUTEGOAL_VIEWPORTALS 4
typedef struct aas_altroutegoal_s
{
vec3_t origin;
int areanum;
unsigned short starttraveltime;
unsigned short goaltraveltime;
unsigned short extratraveltime;
} aas_altroutegoal_t;
// route prediction stop events
#define RSE_NONE 0
#define RSE_NOROUTE 1 //no route to goal
#define RSE_USETRAVELTYPE 2 //stop as soon as on of the given travel types is used
#define RSE_ENTERCONTENTS 4 //stop when entering the given contents
#define RSE_ENTERAREA 8 //stop when entering the given area
typedef struct aas_predictroute_s
{
vec3_t endpos; //position at the end of movement prediction
int endarea; //area at end of movement prediction
int stopevent; //event that made the prediction stop
int endcontents; //contents at the end of movement prediction
int endtravelflags; //end travel flags
int numareas; //number of areas predicted ahead
int time; //time predicted ahead (in hundreth of a sec)
} aas_predictroute_t;

32
code/game/be_ai_char.h Normal file
View File

@ -0,0 +1,32 @@
// Copyright (C) 2001-2002 Raven Software
//
/*****************************************************************************
* name: be_ai_char.h
*
* desc: bot characters
*
* $Archive: /source/code/botlib/be_ai_char.h $
* $Author: Mrelusive $
* $Revision: 2 $
* $Modtime: 10/05/99 3:32p $
* $Date: 10/05/99 3:42p $
*
*****************************************************************************/
//loads a bot character from a file
int BotLoadCharacter(char *charfile, float skill);
//frees a bot character
void BotFreeCharacter(int character);
//returns a float characteristic
float Characteristic_Float(int character, int index);
//returns a bounded float characteristic
float Characteristic_BFloat(int character, int index, float min, float max);
//returns an integer characteristic
int Characteristic_Integer(int character, int index);
//returns a bounded integer characteristic
int Characteristic_BInteger(int character, int index, int min, int max);
//returns a string characteristic
void Characteristic_String(int character, int index, char *buf, int size);
//free cached bot characters
void BotShutdownCharacters(void);

97
code/game/be_ai_chat.h Normal file
View File

@ -0,0 +1,97 @@
// Copyright (C) 2001-2002 Raven Software
//
/*****************************************************************************
* name: be_ai_chat.h
*
* desc: char AI
*
* $Archive: /source/code/botlib/be_ai_chat.h $
* $Author: Mrelusive $
* $Revision: 2 $
* $Modtime: 10/05/99 3:32p $
* $Date: 10/05/99 3:42p $
*
*****************************************************************************/
#define MAX_MESSAGE_SIZE 256
#define MAX_CHATTYPE_NAME 32
#define MAX_MATCHVARIABLES 8
#define CHAT_GENDERLESS 0
#define CHAT_GENDERFEMALE 1
#define CHAT_GENDERMALE 2
#define CHAT_ALL 0
#define CHAT_TEAM 1
#define CHAT_TELL 2
//a console message
typedef struct bot_consolemessage_s
{
int handle;
float time; //message time
int type; //message type
char message[MAX_MESSAGE_SIZE]; //message
struct bot_consolemessage_s *prev, *next; //prev and next in list
} bot_consolemessage_t;
//match variable
typedef struct bot_matchvariable_s
{
char offset;
int length;
} bot_matchvariable_t;
//returned to AI when a match is found
typedef struct bot_match_s
{
char string[MAX_MESSAGE_SIZE];
int type;
int subtype;
bot_matchvariable_t variables[MAX_MATCHVARIABLES];
} bot_match_t;
//setup the chat AI
int BotSetupChatAI(void);
//shutdown the chat AI
void BotShutdownChatAI(void);
//returns the handle to a newly allocated chat state
int BotAllocChatState(void);
//frees the chatstate
void BotFreeChatState(int handle);
//adds a console message to the chat state
void BotQueueConsoleMessage(int chatstate, int type, char *message);
//removes the console message from the chat state
void BotRemoveConsoleMessage(int chatstate, int handle);
//returns the next console message from the state
int BotNextConsoleMessage(int chatstate, bot_consolemessage_t *cm);
//returns the number of console messages currently stored in the state
int BotNumConsoleMessages(int chatstate);
//selects a chat message of the given type
void BotInitialChat(int chatstate, char *type, int mcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7);
//returns the number of initial chat messages of the given type
int BotNumInitialChats(int chatstate, char *type);
//find and select a reply for the given message
int BotReplyChat(int chatstate, char *message, int mcontext, int vcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7);
//returns the length of the currently selected chat message
int BotChatLength(int chatstate);
//enters the selected chat message
void BotEnterChat(int chatstate, int clientto, int sendto);
//get the chat message ready to be output
void BotGetChatMessage(int chatstate, char *buf, int size);
//checks if the first string contains the second one, returns index into first string or -1 if not found
int StringContains(char *str1, char *str2, int casesensitive);
//finds a match for the given string using the match templates
int BotFindMatch(char *str, bot_match_t *match, unsigned long int context);
//returns a variable from a match
void BotMatchVariable(bot_match_t *match, int variable, char *buf, int size);
//unify all the white spaces in the string
void UnifyWhiteSpaces(char *string);
//replace all the context related synonyms in the string
void BotReplaceSynonyms(char *string, unsigned long int context);
//loads a chat file for the chat state
int BotLoadChatFile(int chatstate, char *chatfile, char *chatname);
//store the gender of the bot in the chat state
void BotSetChatGender(int chatstate, int gender);
//store the bot name in the chat state
void BotSetChatName(int chatstate, char *name, int client);

17
code/game/be_ai_gen.h Normal file
View File

@ -0,0 +1,17 @@
// Copyright (C) 2001-2002 Raven Software
//
/*****************************************************************************
* name: be_ai_gen.h
*
* desc: genetic selection
*
* $Archive: /source/code/botlib/be_ai_gen.h $
* $Author: Mrelusive $
* $Revision: 2 $
* $Modtime: 10/05/99 3:32p $
* $Date: 10/05/99 3:42p $
*
*****************************************************************************/
int GeneticParentsAndChildSelection(int numranks, float *ranks, int *parent1, int *parent2, int *child);

102
code/game/be_ai_goal.h Normal file
View File

@ -0,0 +1,102 @@
// Copyright (C) 2001-2002 Raven Software
//
/*****************************************************************************
* name: be_ai_goal.h
*
* desc: goal AI
*
* $Archive: /source/code/botlib/be_ai_goal.h $
* $Author: Mrelusive $
* $Revision: 2 $
* $Modtime: 10/05/99 3:32p $
* $Date: 10/05/99 3:42p $
*
*****************************************************************************/
#define MAX_AVOIDGOALS 256
#define MAX_GOALSTACK 8
#define GFL_NONE 0
#define GFL_ITEM 1
#define GFL_ROAM 2
#define GFL_DROPPED 4
//a bot goal
typedef struct bot_goal_s
{
vec3_t origin; //origin of the goal
int areanum; //area number of the goal
vec3_t mins, maxs; //mins and maxs of the goal
int entitynum; //number of the goal entity
int number; //goal number
int flags; //goal flags
int iteminfo; //item information
} bot_goal_t;
//reset the whole goal state, but keep the item weights
void BotResetGoalState(int goalstate);
//reset avoid goals
void BotResetAvoidGoals(int goalstate);
//remove the goal with the given number from the avoid goals
void BotRemoveFromAvoidGoals(int goalstate, int number);
//push a goal onto the goal stack
void BotPushGoal(int goalstate, bot_goal_t *goal);
//pop a goal from the goal stack
void BotPopGoal(int goalstate);
//empty the bot's goal stack
void BotEmptyGoalStack(int goalstate);
//dump the avoid goals
void BotDumpAvoidGoals(int goalstate);
//dump the goal stack
void BotDumpGoalStack(int goalstate);
//get the name name of the goal with the given number
void BotGoalName(int number, char *name, int size);
//get the top goal from the stack
int BotGetTopGoal(int goalstate, bot_goal_t *goal);
//get the second goal on the stack
int BotGetSecondGoal(int goalstate, bot_goal_t *goal);
//choose the best long term goal item for the bot
int BotChooseLTGItem(int goalstate, vec3_t origin, int *inventory, int travelflags);
//choose the best nearby goal item for the bot
//the item may not be further away from the current bot position than maxtime
//also the travel time from the nearby goal towards the long term goal may not
//be larger than the travel time towards the long term goal from the current bot position
int BotChooseNBGItem(int goalstate, vec3_t origin, int *inventory, int travelflags,
bot_goal_t *ltg, float maxtime);
//returns true if the bot touches the goal
int BotTouchingGoal(vec3_t origin, bot_goal_t *goal);
//returns true if the goal should be visible but isn't
int BotItemGoalInVisButNotVisible(int viewer, vec3_t eye, vec3_t viewangles, bot_goal_t *goal);
//search for a goal for the given classname, the index can be used
//as a start point for the search when multiple goals are available with that same classname
int BotGetLevelItemGoal(int index, char *classname, bot_goal_t *goal);
//get the next camp spot in the map
int BotGetNextCampSpotGoal(int num, bot_goal_t *goal);
//get the map location with the given name
int BotGetMapLocationGoal(char *name, bot_goal_t *goal);
//returns the avoid goal time
float BotAvoidGoalTime(int goalstate, int number);
//set the avoid goal time
void BotSetAvoidGoalTime(int goalstate, int number, float avoidtime);
//initializes the items in the level
void BotInitLevelItems(void);
//regularly update dynamic entity items (dropped weapons, flags etc.)
void BotUpdateEntityItems(void);
//interbreed the goal fuzzy logic
void BotInterbreedGoalFuzzyLogic(int parent1, int parent2, int child);
//save the goal fuzzy logic to disk
void BotSaveGoalFuzzyLogic(int goalstate, char *filename);
//mutate the goal fuzzy logic
void BotMutateGoalFuzzyLogic(int goalstate, float range);
//loads item weights for the bot
int BotLoadItemWeights(int goalstate, char *filename);
//frees the item weights of the bot
void BotFreeItemWeights(int goalstate);
//returns the handle of a newly allocated goal state
int BotAllocGoalState(int client);
//free the given goal state
void BotFreeGoalState(int handle);
//setup the goal AI
int BotSetupGoalAI(void);
//shut down the goal AI
void BotShutdownGoalAI(void);

126
code/game/be_ai_move.h Normal file
View File

@ -0,0 +1,126 @@
// Copyright (C) 2001-2002 Raven Software
//
/*****************************************************************************
* name: be_ai_move.h
*
* desc: movement AI
*
* $Archive: /source/code/botlib/be_ai_move.h $
* $Author: Mrelusive $
* $Revision: 2 $
* $Modtime: 10/05/99 3:32p $
* $Date: 10/05/99 3:42p $
*
*****************************************************************************/
//movement types
#define MOVE_WALK 1
#define MOVE_CROUCH 2
#define MOVE_JUMP 4
#define MOVE_GRAPPLE 8
#define MOVE_ROCKETJUMP 16
#define MOVE_BFGJUMP 32
//move flags
#define MFL_BARRIERJUMP 1 //bot is performing a barrier jump
#define MFL_ONGROUND 2 //bot is in the ground
#define MFL_SWIMMING 4 //bot is swimming
#define MFL_AGAINSTLADDER 8 //bot is against a ladder
#define MFL_WATERJUMP 16 //bot is waterjumping
#define MFL_TELEPORTED 32 //bot is being teleported
#define MFL_GRAPPLEPULL 64 //bot is being pulled by the grapple
#define MFL_ACTIVEGRAPPLE 128 //bot is using the grapple hook
#define MFL_GRAPPLERESET 256 //bot has reset the grapple
#define MFL_WALK 512 //bot should walk slowly
// move result flags
#define MOVERESULT_MOVEMENTVIEW 1 //bot uses view for movement
#define MOVERESULT_SWIMVIEW 2 //bot uses view for swimming
#define MOVERESULT_WAITING 4 //bot is waiting for something
#define MOVERESULT_MOVEMENTVIEWSET 8 //bot has set the view in movement code
#define MOVERESULT_MOVEMENTWEAPON 16 //bot uses weapon for movement
#define MOVERESULT_ONTOPOFOBSTACLE 32 //bot is ontop of obstacle
#define MOVERESULT_ONTOPOF_FUNCBOB 64 //bot is ontop of a func_bobbing
#define MOVERESULT_ONTOPOF_ELEVATOR 128 //bot is ontop of an elevator (func_plat)
#define MOVERESULT_BLOCKEDBYAVOIDSPOT 256 //bot is blocked by an avoid spot
//
#define MAX_AVOIDREACH 1
#define MAX_AVOIDSPOTS 32
// avoid spot types
#define AVOID_CLEAR 0 //clear all avoid spots
#define AVOID_ALWAYS 1 //avoid always
#define AVOID_DONTBLOCK 2 //never totally block
// restult types
#define RESULTTYPE_ELEVATORUP 1 //elevator is up
#define RESULTTYPE_WAITFORFUNCBOBBING 2 //waiting for func bobbing to arrive
#define RESULTTYPE_BADGRAPPLEPATH 4 //grapple path is obstructed
#define RESULTTYPE_INSOLIDAREA 8 //stuck in solid area, this is bad
//structure used to initialize the movement state
//the or_moveflags MFL_ONGROUND, MFL_TELEPORTED and MFL_WATERJUMP come from the playerstate
typedef struct bot_initmove_s
{
vec3_t origin; //origin of the bot
vec3_t velocity; //velocity of the bot
vec3_t viewoffset; //view offset
int entitynum; //entity number of the bot
int client; //client number of the bot
float thinktime; //time the bot thinks
int presencetype; //presencetype of the bot
vec3_t viewangles; //view angles of the bot
int or_moveflags; //values ored to the movement flags
} bot_initmove_t;
//NOTE: the ideal_viewangles are only valid if MFL_MOVEMENTVIEW is set
typedef struct bot_moveresult_s
{
int failure; //true if movement failed all together
int type; //failure or blocked type
int blocked; //true if blocked by an entity
int blockentity; //entity blocking the bot
int traveltype; //last executed travel type
int flags; //result flags
int weapon; //weapon used for movement
vec3_t movedir; //movement direction
vec3_t ideal_viewangles; //ideal viewangles for the movement
} bot_moveresult_t;
// bk001204: from code/botlib/be_ai_move.c
// TTimo 04/12/2001 was moved here to avoid dup defines
typedef struct bot_avoidspot_s
{
vec3_t origin;
float radius;
int type;
} bot_avoidspot_t;
//resets the whole move state
void BotResetMoveState(int movestate);
//moves the bot to the given goal
void BotMoveToGoal(bot_moveresult_t *result, int movestate, bot_goal_t *goal, int travelflags);
//moves the bot in the specified direction using the specified type of movement
int BotMoveInDirection(int movestate, vec3_t dir, float speed, int type);
//reset avoid reachability
void BotResetAvoidReach(int movestate);
//resets the last avoid reachability
void BotResetLastAvoidReach(int movestate);
//returns a reachability area if the origin is in one
int BotReachabilityArea(vec3_t origin, int client);
//view target based on movement
int BotMovementViewTarget(int movestate, bot_goal_t *goal, int travelflags, float lookahead, vec3_t target);
//predict the position of a player based on movement towards a goal
int BotPredictVisiblePosition(vec3_t origin, int areanum, bot_goal_t *goal, int travelflags, vec3_t target);
//returns the handle of a newly allocated movestate
int BotAllocMoveState(void);
//frees the movestate with the given handle
void BotFreeMoveState(int handle);
//initialize movement state before performing any movement
void BotInitMoveState(int handle, bot_initmove_t *initmove);
//add a spot to avoid (if type == AVOID_CLEAR all spots are removed)
void BotAddAvoidSpot(int movestate, vec3_t origin, float radius, int type);
//must be called every map change
void BotSetBrushModelTypes(void);
//setup movement AI
int BotSetupMoveAI(void);
//shutdown movement AI
void BotShutdownMoveAI(void);

88
code/game/be_ai_weap.h Normal file
View File

@ -0,0 +1,88 @@
// Copyright (C) 2001-2002 Raven Software
//
/*****************************************************************************
* name: be_ai_weap.h
*
* desc: weapon AI
*
* $Archive: /source/code/botlib/be_ai_weap.h $
* $Author: Mrelusive $
* $Revision: 2 $
* $Modtime: 10/05/99 3:32p $
* $Date: 10/05/99 3:42p $
*
*****************************************************************************/
//projectile flags
#define PFL_WINDOWDAMAGE 1 //projectile damages through window
#define PFL_RETURN 2 //set when projectile returns to owner
//weapon flags
#define WFL_FIRERELEASED 1 //set when projectile is fired with key-up event
//damage types
#define DAMAGETYPE_IMPACT 1 //damage on impact
#define DAMAGETYPE_RADIAL 2 //radial damage
#define DAMAGETYPE_VISIBLE 4 //damage to all entities visible to the projectile
typedef struct projectileinfo_s
{
char name[MAX_STRINGFIELD];
char model[MAX_STRINGFIELD];
int flags;
float gravity;
int damage;
float radius;
int visdamage;
int damagetype;
int healthinc;
float push;
float detonation;
float bounce;
float bouncefric;
float bouncestop;
} projectileinfo_t;
typedef struct weaponinfo_s
{
int valid; //true if the weapon info is valid
int number; //number of the weapon
char name[MAX_STRINGFIELD];
char model[MAX_STRINGFIELD];
int level;
int weaponindex;
int flags;
char projectile[MAX_STRINGFIELD];
int numprojectiles;
float hspread;
float vspread;
float speed;
float acceleration;
vec3_t recoil;
vec3_t offset;
vec3_t angleoffset;
float extrazvelocity;
int ammoamount;
int ammoindex;
float activate;
float reload;
float spinup;
float spindown;
projectileinfo_t proj; //pointer to the used projectile
} weaponinfo_t;
//setup the weapon AI
int BotSetupWeaponAI(void);
//shut down the weapon AI
void BotShutdownWeaponAI(void);
//returns the best weapon to fight with
int BotChooseBestFightWeapon(int weaponstate, int *inventory);
//returns the information of the current weapon
void BotGetWeaponInfo(int weaponstate, int weapon, weaponinfo_t *weaponinfo);
//loads the weapon weights
int BotLoadWeaponWeights(int weaponstate, char *filename);
//returns a handle to a newly allocated weapon state
int BotAllocWeaponState(void);
//frees the weapon state
void BotFreeWeaponState(int weaponstate);
//resets the whole weapon state
void BotResetWeaponState(int weaponstate);

52
code/game/be_ea.h Normal file
View File

@ -0,0 +1,52 @@
// Copyright (C) 2001-2002 Raven Software
//
/*****************************************************************************
* name: be_ea.h
*
* desc: elementary actions
*
* $Archive: /source/code/botlib/be_ea.h $
* $Author: Mrelusive $
* $Revision: 2 $
* $Modtime: 10/05/99 3:32p $
* $Date: 10/05/99 3:42p $
*
*****************************************************************************/
//ClientCommand elementary actions
void EA_Say(int client, char *str);
void EA_SayTeam(int client, char *str);
void EA_Command(int client, char *command );
void EA_Action(int client, int action);
void EA_Crouch(int client);
void EA_Walk(int client);
void EA_MoveUp(int client);
void EA_MoveDown(int client);
void EA_MoveForward(int client);
void EA_MoveBack(int client);
void EA_MoveLeft(int client);
void EA_MoveRight(int client);
void EA_Attack(int client);
void EA_Alt_Attack(int client);
void EA_ForcePower(int client);
void EA_Respawn(int client);
void EA_Talk(int client);
void EA_Gesture(int client);
void EA_Use(int client);
//regular elementary actions
void EA_SelectWeapon(int client, int weapon);
void EA_Jump(int client);
void EA_DelayedJump(int client);
void EA_Move(int client, vec3_t dir, float speed);
void EA_View(int client, vec3_t viewangles);
//send regular input to the server
void EA_EndRegular(int client, float thinktime);
void EA_GetInput(int client, float thinktime, bot_input_t *input);
void EA_ResetInput(int client);
//setup and shutdown routines
int EA_Setup(void);
void EA_Shutdown(void);

265
code/game/bg_gametype.c Normal file
View File

@ -0,0 +1,265 @@
// Copyright (C) 2001-2002 Raven Software
//
// bg_gametype.c -- dynamic gametype handling
#include "q_shared.h"
#include "bg_public.h"
#include "bg_local.h"
gametypeData_t bg_gametypeData[MAX_GAMETYPES];
int bg_gametypeCount;
/*
===============
BG_ParseGametypePhotos
Parses the photo information for objectives dialog
===============
*/
static qboolean BG_ParseGametypePhotos ( int gametypeIndex, TGPGroup group )
{
TGPGroup photo;
int index;
char temp[MAX_TOKENLENGTH];
// Convienience check
if ( !group )
{
return qtrue;
}
index = 0;
photo = trap_GPG_GetSubGroups ( group );
while ( photo )
{
trap_GPG_GetName ( photo, temp );
bg_gametypeData[gametypeIndex].photos[index].name = trap_VM_LocalStringAlloc ( temp );
trap_GPG_FindPairValue ( photo, "displayname", "unknown", temp );
bg_gametypeData[gametypeIndex].photos[index].displayName = trap_VM_LocalStringAlloc ( temp );
index++;
photo = trap_GPG_GetNext ( photo );
}
return qtrue;
}
/*
===============
BG_ParseGametypeInfo
Parses minimal information about the given gametype. For the most part
this information is the name of the gametype and some of its parameters.
===============
*/
static qboolean BG_ParseGametypeInfo ( int gametypeIndex )
{
gametypeData_t* gametype;
TGenericParser2 GP2;
TGPGroup topGroup;
TGPGroup gtGroup;
char temp[1024];
// Get the pointer for the gametype data
gametype = &bg_gametypeData[gametypeIndex];
// Open the gametype's script file
GP2 = trap_GP_ParseFile( (char*)gametype->script, qtrue, qfalse);
if (!GP2)
{
return qfalse;
}
// Top group should only contain the "gametype" sub group
topGroup = trap_GP_GetBaseParseGroup(GP2);
if ( !topGroup )
{
return qfalse;
}
// Grab the gametype sub group
gtGroup = trap_GPG_FindSubGroup ( topGroup, "gametype" );
if ( !gtGroup )
{
return qfalse;
}
// Parse out the name of the gametype
trap_GPG_FindPairValue ( gtGroup, "displayname", "", temp );
if ( !temp[0] )
{
return qfalse;
}
gametype->displayName = trap_VM_LocalStringAlloc ( temp );
// Description
trap_GPG_FindPairValue ( gtGroup, "description", "", temp );
if ( temp[0] )
{
gametype->description = trap_VM_LocalStringAlloc ( temp );
}
// Are pickups enabled?
trap_GPG_FindPairValue ( gtGroup, "pickups", "yes", temp );
if ( !Q_stricmp ( temp, "no" ) )
{
gametype->pickupsDisabled = qtrue;
}
// Are teams enabled?
trap_GPG_FindPairValue ( gtGroup, "teams", "yes", temp );
if ( !Q_stricmp ( temp, "yes" ) )
{
gametype->teams = qtrue;
}
// Display kills
trap_GPG_FindPairValue ( gtGroup, "showkills", "no", temp );
if ( !Q_stricmp ( temp, "yes" ) )
{
gametype->showKills = qtrue;
}
// Look for the respawn type
trap_GPG_FindPairValue ( gtGroup, "respawn", "normal", temp );
if ( !Q_stricmp ( temp, "none" ) )
{
gametype->respawnType = RT_NONE;
}
else if ( !Q_stricmp ( temp, "interval" ) )
{
gametype->respawnType = RT_INTERVAL;
}
else
{
gametype->respawnType = RT_NORMAL;
}
// What percentage doest he backpack replenish?
trap_GPG_FindPairValue ( gtGroup, "backpack", "0", temp );
gametype->backpack = atoi(temp);
// Get the photo information for objectives dialog
BG_ParseGametypePhotos ( gametypeIndex, trap_GPG_FindSubGroup ( gtGroup, "photos" ) );
// Cleanup the generic parser
trap_GP_Delete ( &GP2 );
return qtrue;
}
/*
===============
BG_BuildGametypeList
Builds a list of the gametypes that are available and parses minimal
information about those gametypes.
===============
*/
qboolean BG_BuildGametypeList ( void )
{
char filename[MAX_QPATH];
char filelist[4096];
char* fileptr;
char* s;
int filelen;
int filecount;
int i;
bg_gametypeCount = 0;
// Retrieve the list of gametype files. The returned list is a
// null separated list with the number of entries returned by the call
filecount = trap_FS_GetFileList("scripts", ".gametype", filelist, 4096 );
fileptr = filelist;
for ( i = 0; i < filecount; i++, fileptr += filelen+1)
{
// Grab the length so we can skip this file later
filelen = strlen(fileptr);
// Build the full filename
strcpy(filename, "scripts/");
strcat(filename, fileptr );
// Fill in what we know so far
bg_gametypeData[bg_gametypeCount].script = trap_VM_LocalStringAlloc ( filename );
// Kill the dot so we can use the filename as the short name
s = strchr ( fileptr, '.' );
*s = '\0';
bg_gametypeData[bg_gametypeCount].name = trap_VM_LocalStringAlloc ( fileptr );
// TODO: Parse the gametype file
BG_ParseGametypeInfo ( bg_gametypeCount++ );
}
return qtrue;
}
/*
===============
BG_FindGametype
Returns the gametype index using the given name. If the gametype isnt found
then -1 will be returned (and this is bad)
===============
*/
int BG_FindGametype ( const char* name )
{
int i;
// Loop through the known gametypes and compare their names to
// the name given
for ( i = 0; i < bg_gametypeCount; i ++ )
{
// Do the names match?
if ( !Q_stricmp ( bg_gametypeData[i].name, name ) )
{
return i;
}
}
return -1;
}
/*
==============
BG_FindGametypeItem
Search through the item list for the gametype item with
the given index.
==============
*/
gitem_t *BG_FindGametypeItem ( int index )
{
return &bg_itemlist[index + MODELINDEX_GAMETYPE_ITEM];
}
/*
==============
BG_FindGametypeItemByID
Gametype will assign ids to the gametype items for them for future reference, the
id is crammed into the quantity field of the gametype item. This function will
find the gametype item with the given item id.
==============
*/
gitem_t *BG_FindGametypeItemByID ( int itemid )
{
int i;
for ( i = 0; i < MAX_GAMETYPE_ITEMS; i ++ )
{
if ( bg_itemlist[i + MODELINDEX_GAMETYPE_ITEM].quantity == itemid )
{
return &bg_itemlist[i + MODELINDEX_GAMETYPE_ITEM];
}
}
return NULL;
}

1316
code/game/bg_lib.c Normal file

File diff suppressed because it is too large Load Diff

71
code/game/bg_lib.h Normal file
View File

@ -0,0 +1,71 @@
// bg_lib.h -- standard C library replacement routines used by code
// compiled for the virtual machine
// This file is NOT included on native builds
typedef int size_t;
typedef char * va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
#define CHAR_BIT 8 /* number of bits in a char */
#define SCHAR_MIN (-128) /* minimum signed char value */
#define SCHAR_MAX 127 /* maximum signed char value */
#define UCHAR_MAX 0xff /* maximum unsigned char value */
#define SHRT_MIN (-32768) /* minimum (signed) short value */
#define SHRT_MAX 32767 /* maximum (signed) short value */
#define USHRT_MAX 0xffff /* maximum unsigned short value */
#define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */
#define INT_MAX 2147483647 /* maximum (signed) int value */
#define UINT_MAX 0xffffffff /* maximum unsigned int value */
#define LONG_MIN (-2147483647L - 1) /* minimum (signed) long value */
#define LONG_MAX 2147483647L /* maximum (signed) long value */
#define ULONG_MAX 0xffffffffUL /* maximum unsigned long value */
// Misc functions
typedef int cmp_t(const void *, const void *);
void qsort(void *a, size_t n, size_t es, cmp_t *cmp);
void srand( unsigned seed );
int rand( void );
// String functions
size_t strlen( const char *string );
char *strcat( char *strDestination, const char *strSource );
char *strcpy( char *strDestination, const char *strSource );
int strcmp( const char *string1, const char *string2 );
char *strchr( const char *string, int c );
char *strstr( const char *string, const char *strCharSet );
char *strncpy( char *strDest, const char *strSource, size_t count );
int tolower( int c );
int toupper( int c );
double atof( const char *string );
double _atof( const char **stringPtr );
int atoi( const char *string );
int _atoi( const char **stringPtr );
int vsprintf( char *buffer, const char *fmt, va_list argptr );
int sscanf( const char *buffer, const char *fmt, ... );
// Memory functions
void *memmove( void *dest, const void *src, size_t count );
void *memset( void *dest, int c, size_t count );
void *memcpy( void *dest, const void *src, size_t count );
// Math functions
double ceil( double x );
double floor( double x );
double sqrt( double x );
double sin( double x );
double cos( double x );
double atan2( double y, double x );
double tan( double x );
int abs( int n );
double fabs( double x );
double acos( double x );
double asin( double x );

70
code/game/bg_local.h Normal file
View File

@ -0,0 +1,70 @@
// Copyright (C) 2001-2002 Raven Software.
//
// bg_local.h -- local definitions for the bg (both games) files
#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes
#define MIN_WALK_NORMAL_TERRAIN 0.625f // bit steeper for terrain
#define STEPSIZE 18
#define JUMP_VELOCITY 270
#define TIMER_LAND 130
#define TIMER_GESTURE (34*66+50)
#define OVERCLIP 1.001f
// all of the locals will be zeroed before each
// pmove, just to make damn sure we don't have
// any differences when running on client or server
typedef struct
{
vec3_t forward, right, up;
float frametime;
int msec;
qboolean walking;
qboolean groundPlane;
trace_t groundTrace;
float impactSpeed;
vec3_t previous_origin;
vec3_t previous_velocity;
int previous_waterlevel;
} pml_t;
extern pml_t pml;
// movement parameters
extern float pm_stopspeed;
extern float pm_duckScale;
extern float pm_swimScale;
extern float pm_wadeScale;
extern float pm_accelerate;
extern float pm_airaccelerate;
extern float pm_wateraccelerate;
extern float pm_flyaccelerate;
extern float pm_friction;
extern float pm_waterfriction;
extern float pm_flightfriction;
extern int c_pmove;
void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce );
void PM_AddTouchEnt( int entityNum );
void PM_AddEvent( int newEvent );
void PM_AddEventWithParm( int newEvent, int parm );
qboolean PM_SlideMove( qboolean gravity );
void PM_StepSlideMove( qboolean gravity );
void PM_StartTorsoAnim ( playerState_t* ps, int anim, int time );
void PM_ContinueLegsAnim ( playerState_t* ps, int anim );
void PM_ForceLegsAnim ( playerState_t* ps, int anim );
void PM_TorsoAnimation ( playerState_t* ps );
void PM_SetAnim ( playerState_t* ps, int setAnimParts,int anim,int setAnimFlags, int blendTime);

1622
code/game/bg_misc.c Normal file

File diff suppressed because it is too large Load Diff

1741
code/game/bg_player.c Normal file

File diff suppressed because it is too large Load Diff

3901
code/game/bg_pmove.c Normal file

File diff suppressed because it is too large Load Diff

1137
code/game/bg_public.h Normal file

File diff suppressed because it is too large Load Diff

352
code/game/bg_slidemove.c Normal file
View File

@ -0,0 +1,352 @@
// Copyright (C) 2001-2002 Raven Software
//
// bg_slidemove.c -- part of bg_pmove functionality
#include "q_shared.h"
#include "bg_public.h"
#include "bg_local.h"
/*
==================
PM_SlideMove
Returns qtrue if the velocity was clipped in some way
==================
*/
#define MAX_CLIP_PLANES 5
qboolean PM_SlideMove( qboolean gravity )
{
int bumpcount, numbumps;
vec3_t dir;
float d;
int numplanes;
vec3_t planes[MAX_CLIP_PLANES];
vec3_t primal_velocity;
vec3_t clipVelocity;
int i, j, k;
trace_t trace;
vec3_t end;
float time_left;
float into;
vec3_t endVelocity;
vec3_t endClipVelocity;
numbumps = 4;
VectorCopy (pm->ps->velocity, primal_velocity);
if ( gravity )
{
VectorCopy( pm->ps->velocity, endVelocity );
endVelocity[2] -= pm->ps->gravity * pml.frametime;
pm->ps->velocity[2] = ( pm->ps->velocity[2] + endVelocity[2] ) * 0.5;
primal_velocity[2] = endVelocity[2];
if ( pml.groundPlane )
{
// slide along the ground plane
PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal,
pm->ps->velocity, OVERCLIP );
}
}
time_left = pml.frametime;
// never turn against the ground plane
if ( pml.groundPlane )
{
numplanes = 1;
VectorCopy( pml.groundTrace.plane.normal, planes[0] );
}
else
{
numplanes = 0;
}
// never turn against original velocity
VectorNormalize2( pm->ps->velocity, planes[numplanes] );
numplanes++;
for ( bumpcount=0 ; bumpcount < numbumps ; bumpcount++ )
{
// calculate position we are trying to move to
VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end );
// see if we can make it there
pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask);
if (trace.allsolid)
{
// entity is completely trapped in another solid
pm->ps->velocity[2] = 0; // don't build up falling damage, but allow sideways acceleration
return qtrue;
}
if (trace.fraction > 0)
{
// actually covered some distance
VectorCopy (trace.endpos, pm->ps->origin);
}
if (trace.fraction == 1)
{
break; // moved the entire distance
}
// save entity for contact
PM_AddTouchEnt( trace.entityNum );
time_left -= time_left * trace.fraction;
if (numplanes >= MAX_CLIP_PLANES)
{
// this shouldn't really happen
VectorClear( pm->ps->velocity );
return qtrue;
}
//
// if this is the same plane we hit before, nudge velocity
// out along it, which fixes some epsilon issues with
// non-axial planes
//
for ( i = 0 ; i < numplanes ; i++ )
{
if ( DotProduct( trace.plane.normal, planes[i] ) > 0.99 )
{
VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity );
break;
}
}
if ( i < numplanes )
{
continue;
}
VectorCopy (trace.plane.normal, planes[numplanes]);
numplanes++;
//
// modify velocity so it parallels all of the clip planes
//
// find a plane that it enters
for ( i = 0 ; i < numplanes ; i++ )
{
into = DotProduct( pm->ps->velocity, planes[i] );
if ( into >= 0.1 )
{
continue; // move doesn't interact with the plane
}
// see how hard we are hitting things
if ( -into > pml.impactSpeed )
{
pml.impactSpeed = -into;
}
// slide along the plane
PM_ClipVelocity (pm->ps->velocity, planes[i], clipVelocity, OVERCLIP );
// slide along the plane
PM_ClipVelocity (endVelocity, planes[i], endClipVelocity, OVERCLIP );
// see if there is a second plane that the new move enters
for ( j = 0 ; j < numplanes ; j++ )
{
if ( j == i )
{
continue;
}
if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 )
{
continue; // move doesn't interact with the plane
}
// try clipping the move to the plane
PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
// see if it goes back into the first clip plane
if ( DotProduct( clipVelocity, planes[i] ) >= 0 )
{
continue;
}
// slide the original velocity along the crease
CrossProduct (planes[i], planes[j], dir);
VectorNormalize( dir );
d = DotProduct( dir, pm->ps->velocity );
VectorScale( dir, d, clipVelocity );
CrossProduct (planes[i], planes[j], dir);
VectorNormalize( dir );
d = DotProduct( dir, endVelocity );
VectorScale( dir, d, endClipVelocity );
// see if there is a third plane the the new move enters
for ( k = 0 ; k < numplanes ; k++ )
{
if ( k == i || k == j )
{
continue;
}
if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 )
{
continue; // move doesn't interact with the plane
}
// stop dead at a tripple plane interaction
VectorClear( pm->ps->velocity );
return qtrue;
}
}
// if we have fixed all interactions, try another move
VectorCopy( clipVelocity, pm->ps->velocity );
VectorCopy( endClipVelocity, endVelocity );
break;
}
}
if ( gravity )
{
VectorCopy( endVelocity, pm->ps->velocity );
}
// don't change velocity if in a timer (FIXME: is this correct?)
if ( pm->ps->pm_time )
{
VectorCopy( primal_velocity, pm->ps->velocity );
}
return (qboolean)( bumpcount != 0 );
}
/*
==================
PM_StepSlideMove
==================
*/
void PM_StepSlideMove( qboolean gravity )
{
trace_t trace;
vec3_t down;
vec3_t up = {0, 0, 1};
qboolean result = qtrue;
vec3_t start_o;
vec3_t start_v;
vec3_t save_o;
vec3_t save_v;
int stepsize;
float delta;
VectorCopy (pm->ps->origin, start_o);
VectorCopy (pm->ps->velocity, start_v);
if ( PM_SlideMove( gravity ) == 0 )
{
// we got exactly where we wanted to go on the first try
return;
}
// Set the standard stepsize
stepsize = STEPSIZE;
// Add to the step size if we are crouched when jumping
if ( pm->ps->pm_flags & PMF_CROUCH_JUMP )
{
stepsize += (DEFAULT_VIEWHEIGHT-CROUCH_VIEWHEIGHT);
}
// Save the origin and velocity in case we have to undo
VectorCopy ( pm->ps->origin, save_o );
VectorCopy ( pm->ps->velocity, save_v );
// First lets see if there is any hope of steping up
pm->maxs[2] -= stepsize;
VectorCopy ( start_o, pm->ps->origin );
VectorCopy ( start_v, pm->ps->velocity );
pm->ps->origin[2] += stepsize;
// try the move with the altered hit box
if ( PM_SlideMove( gravity ))
{
}
// See how far down now
VectorCopy ( pm->ps->origin, down );
down[2] -= stepsize;
// Trace it
pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
// Return the players hitbox to normal
pm->maxs[2] += stepsize;
// No stepping up if you have upward velocity
if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7))
{
VectorCopy ( save_o, pm->ps->origin );
VectorCopy ( save_v, pm->ps->velocity );
return;
}
if ( trace.allsolid || trace.startsolid )
{
result = qfalse;
}
else
{
if ( trace.fraction < 1.0 )
PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP );
// Now double check not stuck
VectorCopy ( trace.endpos, pm->ps->origin );
pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask);
if ( trace.allsolid || trace.startsolid )
result = qfalse;
}
if ( !result )
{
VectorCopy ( save_o, pm->ps->origin );
VectorCopy ( save_v, pm->ps->velocity );
}
// use the step move
delta = pm->ps->origin[2] - start_o[2];
// Shoould we send a step event?
if ( delta > 2 )
{
if ( delta < 7 )
{
PM_AddEvent( EV_STEP_4 );
}
else if ( delta < 11 )
{
PM_AddEvent( EV_STEP_8 );
}
else if ( delta < 15 )
{
PM_AddEvent( EV_STEP_12 );
}
else
{
PM_AddEvent( EV_STEP_16 );
}
}
if ( pm->debugLevel )
{
Com_Printf("%i:stepped\n", c_pmove);
}
}

1234
code/game/bg_weapons.c Normal file

File diff suppressed because it is too large Load Diff

369
code/game/bg_weapons.h Normal file
View File

@ -0,0 +1,369 @@
// Copyright (C) 2001-2002 Raven Software
//
// bg_weapons.h - weapons data loading
#ifndef __BG_WEAPONS_H__
#define __BG_WEAPONS_H__
// means of death
typedef enum
{
MOD_UNKNOWN,
// Knife
MOD_KNIFE,
// Pistols
MOD_M1911A1_PISTOL,
MOD_USSOCOM_PISTOL,
// Secondarys
MOD_M590_SHOTGUN,
MOD_MICRO_UZI_SUBMACHINEGUN,
MOD_M3A1_SUBMACHINEGUN,
// Primaries
MOD_USAS_12_SHOTGUN,
MOD_M4_ASSAULT_RIFLE,
MOD_AK74_ASSAULT_RIFLE,
MOD_MSG90A1_SNIPER_RIFLE,
MOD_M60_MACHINEGUN,
MOD_MM1_GRENADE_LAUNCHER,
MOD_RPG7_LAUNCHER,
// Grenades
MOD_M67_GRENADE,
MOD_M84_GRENADE,
MOD_F1_GRENADE,
MOD_L2A2_GRENADE,
MOD_MDN11_GRENADE,
MOD_SMOHG92_GRENADE,
MOD_ANM14_GRENADE,
MOD_M15_GRENADE,
MOD_WATER,
MOD_CRUSH,
MOD_TELEFRAG,
MOD_FALLING,
MOD_SUICIDE,
MOD_TEAMCHANGE,
MOD_TARGET_LASER,
MOD_TRIGGER_HURT
} meansOfDeath_t;
typedef enum
{
WP_NONE,
// Knife
WP_KNIFE,
// Pistols
WP_M1911A1_PISTOL,
WP_USSOCOM_PISTOL,
// Secondarys
WP_M590_SHOTGUN,
WP_MICRO_UZI_SUBMACHINEGUN,
WP_M3A1_SUBMACHINEGUN,
// Primaries
WP_USAS_12_SHOTGUN,
WP_M4_ASSAULT_RIFLE,
WP_AK74_ASSAULT_RIFLE,
WP_MSG90A1,
WP_M60_MACHINEGUN,
WP_MM1_GRENADE_LAUNCHER,
WP_RPG7_LAUNCHER,
// Grenades
WP_M67_GRENADE,
WP_M84_GRENADE,
WP_F1_GRENADE,
WP_L2A2_GRENADE,
WP_MDN11_GRENADE,
WP_SMOHG92_GRENADE,
WP_ANM14_GRENADE,
WP_M15_GRENADE,
WP_NUM_WEAPONS
} weapon_t;
#define WP_DELAYED_CHANGE_BIT (1<<5)
typedef enum
{
AMMO_KNIFE,
AMMO_045,
AMMO_556,
AMMO_9 ,
AMMO_12 ,
AMMO_762,
AMMO_40,
AMMO_RPG7,
AMMO_M15,
AMMO_M67,
AMMO_M84,
AMMO_F1,
AMMO_L2A2,
AMMO_MDN11,
AMMO_SMOHG92,
AMMO_ANM14,
AMMO_MAX,
AMMO_NONE,
} ammo_t;
#define WP_FIREMODE_NONE 0
#define WP_FIREMODE_AUTO 1
#define WP_FIREMODE_BURST 2
#define WP_FIREMODE_SINGLE 3
#define WP_FIREMODE_MAX 4
#define PROJECTILE_FIRE 0x0010 // projectile NOT bullet
#define PROJECTILE_TIMED 0x0020 // projectile ONLY explodes after time is up
#define PROJECTILE_GRAVITY 0x0040 // projectile obeys gravity
#define PROJECTILE_DAMAGE_AREA 0x0080 // projectile does area damage over time
#define UNLOCK_MUZZLEFLASH 0x0100 // muzzle flash is locked to muzzle bolt by default
#define PROJECTILE_LIGHTGRAVITY 0x0200 // projectile has light gravity
typedef enum
{
CAT_NONE = 0,
CAT_KNIFE,
CAT_PISTOL,
CAT_SHOTGUN,
CAT_SUB,
CAT_ASSAULT,
CAT_SNIPER,
CAT_HEAVY,
CAT_GRENADE,
CAT_MAX
} ECategory;
typedef struct attackData_s
{
char name[MAX_QPATH];
char icon[MAX_QPATH];
const char* melee;
meansOfDeath_t mod; // means of death
int ammoIndex; // Index to proper ammo slot
union
{
int range; // Range of weapon
int velocity; // speed of projectile
} rV;
int clipSize; // how large is a clip
int fireAmount; // how much ammo to use per shot
int fireFromClip; // 0 = fire from approp. ammo pool, 1 = fire from clip
int damage; // how much damage is done per hit
float inaccuracy; // how inaccurate is weapon
float maxInaccuracy; // maximum lvl of inaccuracy
int pellets; // how many individual 'bullets' are shot with one trigger pull?
int weaponFlags; // which fire modes are available, projectiles timed or impact, .etc
int projectileLifetime; // how long does projectile live (before exploding)
int splashRadius; // how large is splash damage radius
int fireDelay; // Extra delay when firing
qboolean gore; // is gore enabled for this attack?
int extraClips; // Extra clips you get when starting
float bounceScale; // how much something bounces
vec3_t minKickAngles;
vec3_t maxKickAngles;
// Names of effects, sounds, models, bones
char muzzleEffect[MAX_QPATH];
char muzzleEffectBone[MAX_QPATH];
char muzzleEffectInWorld[MAX_QPATH];
char tracerEffect[MAX_QPATH];
char ejectBone[MAX_QPATH];
char shellEject[MAX_QPATH];
char explosionSound[MAX_QPATH];
char explosionEffect[MAX_QPATH];
char missileG2Model[MAX_QPATH];
int animFire;
int animFireZoomed;
} attackData_t;
typedef struct weaponData_s
{
char *classname; // Spawning name
ECategory category; // what group of weapons is this one part of?
qboolean safe;
char worldModel[MAX_QPATH]; // world model
char menuImage[MAX_QPATH]; // names of the icon files
int animDrop;
int animRaise;
int animIdle;
int animIdleZoomed;
int animReload;
int animReloadStart;
int animReloadEnd;
attackData_t attack[ATTACK_MAX];
} weaponData_t;
typedef struct ammoData_s
{
char *name; // name of ammo
char icon[32]; // Name of ammo icon file
int max; // Max amount player can hold of ammo
float goreScale;
} ammoData_t;
extern char *weaponNames[WP_NUM_WEAPONS];
extern weaponData_t weaponData[WP_NUM_WEAPONS];
extern char *ammoNames[AMMO_MAX];
extern ammoData_t ammoData[AMMO_MAX];
// Specific weapon information
#define WP_FIRST_RANGED_WEAPON WP_M1911A1_PISTOL // this is the first weapon for next and prev weapon switching
#define WP_FIRST_MELEE_WEAPON WP_KNIFE
#define MAX_PLAYER_WEAPONS (WP_NUM_WEAPONS-1) // this is the max you can switch to and get with the give all.
#define MAX_WEAPON_SOUNDS 12
#define MAX_WEAPON_SOUND_SLOTS 3
#define MAX_SIDE_SURFACES 16
typedef struct SOptionalWeapon
{
char mName[MAX_QPATH];
char mMuzzle[MAX_QPATH];
char *mSurfaces[MAX_SIDE_SURFACES];
struct SOptionalWeapon *mNext;
} TOptionalWeapon;
typedef struct SBoltonWeapon
{
char mName[MAX_QPATH];
char mModel[MAX_QPATH];
char mParent[MAX_QPATH];
char mBoltToBone[MAX_QPATH];
char *mRightSide[MAX_SIDE_SURFACES];
char mJointBone[MAX_QPATH];
char mJointParentBone[MAX_QPATH];
char mJointForward[10];
char mJointRight[10];
char mJointUp[10];
} TBoltonWeapon;
typedef struct SNoteTrack
{
char mNote[64];
int mFrame;
struct SNoteTrack *mNext;
} TNoteTrack;
#define MAX_WEAPON_ANIM_CHOICES 4
typedef struct SAnimInfoWeapon
{
char mName[MAX_QPATH];
char mType[MAX_QPATH];
char *mAnim[MAX_WEAPON_ANIM_CHOICES];
char *mTransition[MAX_WEAPON_ANIM_CHOICES];
char *mEnd[MAX_WEAPON_ANIM_CHOICES];
float mSpeed;
int mLODBias;
int mNumChoices;
int mStartFrame[MAX_WEAPON_ANIM_CHOICES];
int mNumFrames[MAX_WEAPON_ANIM_CHOICES];
int mFPS[MAX_WEAPON_ANIM_CHOICES];
struct SNoteTrack *mNoteTracks[MAX_WEAPON_ANIM_CHOICES];
struct SAnimInfoWeapon *mNext;
} TAnimInfoWeapon;
typedef struct SAnimWeapon
{
char mName[MAX_QPATH];
char mMuzzle[MAX_QPATH];
struct SAnimInfoWeapon *mInfos;
struct SAnimInfoWeapon *mWeaponModelInfo; // "weaponmodel" info
struct SAnimWeapon *mNext;
} TAnimWeapon;
typedef struct SWeaponModel
{
char mName[MAX_QPATH];
char mModel[MAX_QPATH];
char mBufferName[MAX_QPATH];
char mBufferModel[MAX_QPATH];
char mBufferBoltToBone[MAX_QPATH];
char mBufferMuzzle[MAX_QPATH];
char mBufferAltMuzzle[MAX_QPATH];
char mLeftHandsBoltToBone[MAX_QPATH];
char mRightHandsBoltToBone[MAX_QPATH];
char *mFrontSurfaces[MAX_SIDE_SURFACES],
*mRightSideSurfaces[MAX_SIDE_SURFACES],
*mLeftSideSurfaces[MAX_SIDE_SURFACES];
struct SOptionalWeapon *mOptionalList;
struct SBoltonWeapon *mBolton;
} TWeaponModel;
#define MAX_CALLBACK_SURFACES 4
typedef struct SOnOffSurface
{
char mName[64];
int mStatus;
} TOnOffSurface;
typedef struct SSurfaceCallback
{
char mName[64];
struct SOnOffSurface mOnOffSurfaces[MAX_CALLBACK_SURFACES];
} TSurfaceCallback;
#define MAX_SURFACE_CALLBACKS 2
typedef struct SWeaponInfo
{
char *mName;
float mForeshorten;
vec3_t mViewOffset;
char mSoundNames[MAX_WEAPON_SOUNDS][MAX_QPATH];
char mSounds[MAX_WEAPON_SOUNDS][MAX_WEAPON_SOUND_SLOTS][MAX_QPATH];
struct SSurfaceCallback mSurfaceCallbacks[MAX_SURFACE_CALLBACKS];
struct SAnimWeapon *mAnimList;
struct SWeaponModel mWeaponModel;
} TWeaponParseInfo;
extern TWeaponParseInfo weaponParseInfo[WP_NUM_WEAPONS];
extern char weaponLeftHand[MAX_QPATH];
extern char weaponRightHand[MAX_QPATH];
qboolean BG_ParseInviewFile ( void);
TAnimWeapon* BG_GetInviewAnim ( int weaponIdx,const char *animKey,int *animIndex);
TAnimWeapon* BG_GetInviewAnimFromIndex ( int weaponIdx,int animIndex);
TAnimInfoWeapon* BG_GetInviewModelAnim ( int weaponIdx,const char *modelKey,const char *animKey);
qboolean BG_WeaponHasAlternateAmmo ( int weapon );
int BG_FindFireMode ( weapon_t weapon, attackType_t attack, int firemode );
void BG_CalculateBulletEndpoint ( vec3_t muzzlePoint, vec3_t fireAngs, float inaccuracy, float range, vec3_t end, int *seed );
int BG_GetMaxAmmo ( const playerState_t* ps, int ammoIndex );
#endif

508
code/game/botlib.h Normal file
View File

@ -0,0 +1,508 @@
// Copyright (C) 2001-2002 Raven Software
//
/*****************************************************************************
* name: botlib.h
*
* desc: bot AI library
*
* $Archive: /source/code/game/botai.h $
* $Author: Mrelusive $
* $Revision: 2 $
* $Modtime: 03/01/00 3:32p $
* $Date: 03/01/00 3:42p $
*
*****************************************************************************/
#define BOTLIB_API_VERSION 2
struct aas_clientmove_s;
struct aas_entityinfo_s;
struct aas_areainfo_s;
struct aas_altroutegoal_s;
struct aas_predictroute_s;
struct bot_consolemessage_s;
struct bot_match_s;
struct bot_goal_s;
struct bot_moveresult_s;
struct bot_initmove_s;
struct weaponinfo_s;
#define BOTFILESBASEFOLDER "botfiles"
//debug line colors
#define LINECOLOR_NONE -1
#define LINECOLOR_RED 1//0xf2f2f0f0L
#define LINECOLOR_GREEN 2//0xd0d1d2d3L
#define LINECOLOR_BLUE 3//0xf3f3f1f1L
#define LINECOLOR_YELLOW 4//0xdcdddedfL
#define LINECOLOR_ORANGE 5//0xe0e1e2e3L
//Print types
#define PRT_MESSAGE 1
#define PRT_WARNING 2
#define PRT_ERROR 3
#define PRT_FATAL 4
#define PRT_EXIT 5
//console message types
#define CMS_NORMAL 0
#define CMS_CHAT 1
//botlib error codes
#define BLERR_NOERROR 0 //no error
#define BLERR_LIBRARYNOTSETUP 1 //library not setup
#define BLERR_INVALIDENTITYNUMBER 2 //invalid entity number
#define BLERR_NOAASFILE 3 //no AAS file available
#define BLERR_CANNOTOPENAASFILE 4 //cannot open AAS file
#define BLERR_WRONGAASFILEID 5 //incorrect AAS file id
#define BLERR_WRONGAASFILEVERSION 6 //incorrect AAS file version
#define BLERR_CANNOTREADAASLUMP 7 //cannot read AAS file lump
#define BLERR_CANNOTLOADICHAT 8 //cannot load initial chats
#define BLERR_CANNOTLOADITEMWEIGHTS 9 //cannot load item weights
#define BLERR_CANNOTLOADITEMCONFIG 10 //cannot load item config
#define BLERR_CANNOTLOADWEAPONWEIGHTS 11 //cannot load weapon weights
#define BLERR_CANNOTLOADWEAPONCONFIG 12 //cannot load weapon config
//action flags
#define ACTION_ATTACK 0x0000001
#define ACTION_USE 0x0000002
#define ACTION_RESPAWN 0x0000008
#define ACTION_JUMP 0x0000010
#define ACTION_MOVEUP 0x0000020
#define ACTION_CROUCH 0x0000080
#define ACTION_MOVEDOWN 0x0000100
#define ACTION_MOVEFORWARD 0x0000200
#define ACTION_MOVEBACK 0x0000800
#define ACTION_MOVELEFT 0x0001000
#define ACTION_MOVERIGHT 0x0002000
#define ACTION_DELAYEDJUMP 0x0008000
#define ACTION_TALK 0x0010000
#define ACTION_GESTURE 0x0020000
#define ACTION_WALK 0x0080000
#define ACTION_FORCEPOWER 0x0100000
#define ACTION_ALT_ATTACK 0x0200000
/*
#define ACTION_AFFIRMATIVE 0x0100000
#define ACTION_NEGATIVE 0x0200000
#define ACTION_GETFLAG 0x0800000
#define ACTION_GUARDBASE 0x1000000
#define ACTION_PATROL 0x2000000
#define ACTION_FOLLOWME 0x8000000
*/
//the bot input, will be converted to an usercmd_t
typedef struct bot_input_s
{
float thinktime; //time since last output (in seconds)
vec3_t dir; //movement direction
float speed; //speed in the range [0, 400]
vec3_t viewangles; //the view angles
int actionflags; //one of the ACTION_? flags
int weapon; //weapon to use
} bot_input_t;
#ifndef BSPTRACE
#define BSPTRACE
//bsp_trace_t hit surface
typedef struct bsp_surface_s
{
char name[16];
int flags;
int value;
} bsp_surface_t;
//remove the bsp_trace_s structure definition l8r on
//a trace is returned when a box is swept through the world
typedef struct bsp_trace_s
{
qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
cplane_t plane; // surface normal at impact
float exp_dist; // expanded plane distance
int sidenum; // number of the brush side hit
bsp_surface_t surface; // the hit point surface
int contents; // contents on other side of surface hit
int ent; // number of entity hit
} bsp_trace_t;
#endif // BSPTRACE
//entity state
typedef struct bot_entitystate_s
{
int type; // entity type
int flags; // entity flags
vec3_t origin; // origin of the entity
vec3_t angles; // angles of the model
vec3_t old_origin; // for lerping
vec3_t mins; // bounding box minimums
vec3_t maxs; // bounding box maximums
int groundent; // ground entity
int solid; // solid type
int modelindex; // model used
int modelindex2; // weapons, CTF flags, etc
int frame; // model frame number
int event; // impulse events -- muzzle flashes, footsteps, etc
int eventParm; // even parameter
int gametypeitems; // bit flags
int weapon; // determines weapon and flash model, etc
int legsAnim; // mask off ANIM_TOGGLEBIT
int torsoAnim; // mask off ANIM_TOGGLEBIT
} bot_entitystate_t;
//bot AI library exported functions
typedef struct botlib_import_s
{
//print messages from the bot library
void (QDECL *Print)(int type, char *fmt, ...);
//trace a bbox through the world
void (*Trace)(bsp_trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask);
//trace a bbox against a specific entity
void (*EntityTrace)(bsp_trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int entnum, int contentmask);
//retrieve the contents at the given point
int (*PointContents)(vec3_t point);
//check if the point is in potential visible sight
int (*inPVS)(vec3_t p1, vec3_t p2);
//retrieve the BSP entity data lump
char *(*BSPEntityData)(void);
//
void (*BSPModelMinsMaxsOrigin)(int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin);
//send a bot client command
void (*BotClientCommand)(int client, char *command);
//memory allocation
void *(*GetMemory)(int size); // allocate from Zone
void (*FreeMemory)(void *ptr); // free memory from Zone
int (*AvailableMemory)(void); // available Zone memory
void *(*HunkAlloc)(int size); // allocate from hunk
//file system access
int (*FS_FOpenFile)( const char *qpath, fileHandle_t *file, fsMode_t mode );
int (*FS_Read)( void *buffer, int len, fileHandle_t f );
int (*FS_Write)( const void *buffer, int len, fileHandle_t f );
void (*FS_FCloseFile)( fileHandle_t f );
int (*FS_Seek)( fileHandle_t f, long offset, int origin );
//debug visualisation stuff
int (*DebugLineCreate)(void);
void (*DebugLineDelete)(int line);
void (*DebugLineShow)(int line, vec3_t start, vec3_t end, int color);
//
int (*DebugPolygonCreate)(int color, int numPoints, vec3_t *points);
void (*DebugPolygonDelete)(int id);
} botlib_import_t;
typedef struct aas_export_s
{
//-----------------------------------
// be_aas_entity.h
//-----------------------------------
void (*AAS_EntityInfo)(int entnum, struct aas_entityinfo_s *info);
//-----------------------------------
// be_aas_main.h
//-----------------------------------
int (*AAS_Initialized)(void);
void (*AAS_PresenceTypeBoundingBox)(int presencetype, vec3_t mins, vec3_t maxs);
float (*AAS_Time)(void);
//--------------------------------------------
// be_aas_sample.c
//--------------------------------------------
int (*AAS_PointAreaNum)(vec3_t point);
int (*AAS_PointReachabilityAreaIndex)( vec3_t point );
int (*AAS_TraceAreas)(vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas);
int (*AAS_BBoxAreas)(vec3_t absmins, vec3_t absmaxs, int *areas, int maxareas);
int (*AAS_AreaInfo)( int areanum, struct aas_areainfo_s *info );
//--------------------------------------------
// be_aas_bspq3.c
//--------------------------------------------
int (*AAS_PointContents)(vec3_t point);
int (*AAS_NextBSPEntity)(int ent);
int (*AAS_ValueForBSPEpairKey)(int ent, char *key, char *value, int size);
int (*AAS_VectorForBSPEpairKey)(int ent, char *key, vec3_t v);
int (*AAS_FloatForBSPEpairKey)(int ent, char *key, float *value);
int (*AAS_IntForBSPEpairKey)(int ent, char *key, int *value);
//--------------------------------------------
// be_aas_reach.c
//--------------------------------------------
int (*AAS_AreaReachability)(int areanum);
//--------------------------------------------
// be_aas_route.c
//--------------------------------------------
int (*AAS_AreaTravelTimeToGoalArea)(int areanum, vec3_t origin, int goalareanum, int travelflags);
int (*AAS_EnableRoutingArea)(int areanum, int enable);
int (*AAS_PredictRoute)(struct aas_predictroute_s *route, int areanum, vec3_t origin,
int goalareanum, int travelflags, int maxareas, int maxtime,
int stopevent, int stopcontents, int stoptfl, int stopareanum);
//--------------------------------------------
// be_aas_altroute.c
//--------------------------------------------
int (*AAS_AlternativeRouteGoals)(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
struct aas_altroutegoal_s *altroutegoals, int maxaltroutegoals,
int type);
//--------------------------------------------
// be_aas_move.c
//--------------------------------------------
int (*AAS_Swimming)(vec3_t origin);
int (*AAS_PredictClientMovement)(struct aas_clientmove_s *move,
int entnum, vec3_t origin,
int presencetype, int onground,
vec3_t velocity, vec3_t cmdmove,
int cmdframes,
int maxframes, float frametime,
int stopevent, int stopareanum, int visualize);
} aas_export_t;
typedef struct ea_export_s
{
//ClientCommand elementary actions
void (*EA_Command)(int client, char *command );
void (*EA_Say)(int client, char *str);
void (*EA_SayTeam)(int client, char *str);
//
void (*EA_Action)(int client, int action);
void (*EA_Gesture)(int client);
void (*EA_Talk)(int client);
void (*EA_Attack)(int client);
void (*EA_Use)(int client);
void (*EA_Respawn)(int client);
void (*EA_MoveUp)(int client);
void (*EA_MoveDown)(int client);
void (*EA_MoveForward)(int client);
void (*EA_MoveBack)(int client);
void (*EA_MoveLeft)(int client);
void (*EA_MoveRight)(int client);
void (*EA_Crouch)(int client);
void (*EA_Alt_Attack)(int client);
void (*EA_ForcePower)(int client);
void (*EA_SelectWeapon)(int client, int weapon);
void (*EA_Jump)(int client);
void (*EA_DelayedJump)(int client);
void (*EA_Move)(int client, vec3_t dir, float speed);
void (*EA_View)(int client, vec3_t viewangles);
//send regular input to the server
void (*EA_EndRegular)(int client, float thinktime);
void (*EA_GetInput)(int client, float thinktime, bot_input_t *input);
void (*EA_ResetInput)(int client);
} ea_export_t;
typedef struct ai_export_s
{
//-----------------------------------
// be_ai_char.h
//-----------------------------------
int (*BotLoadCharacter)(char *charfile, float skill);
void (*BotFreeCharacter)(int character);
float (*Characteristic_Float)(int character, int index);
float (*Characteristic_BFloat)(int character, int index, float min, float max);
int (*Characteristic_Integer)(int character, int index);
int (*Characteristic_BInteger)(int character, int index, int min, int max);
void (*Characteristic_String)(int character, int index, char *buf, int size);
//-----------------------------------
// be_ai_chat.h
//-----------------------------------
int (*BotAllocChatState)(void);
void (*BotFreeChatState)(int handle);
void (*BotQueueConsoleMessage)(int chatstate, int type, char *message);
void (*BotRemoveConsoleMessage)(int chatstate, int handle);
int (*BotNextConsoleMessage)(int chatstate, struct bot_consolemessage_s *cm);
int (*BotNumConsoleMessages)(int chatstate);
void (*BotInitialChat)(int chatstate, char *type, int mcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7);
int (*BotNumInitialChats)(int chatstate, char *type);
int (*BotReplyChat)(int chatstate, char *message, int mcontext, int vcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7);
int (*BotChatLength)(int chatstate);
void (*BotEnterChat)(int chatstate, int client, int sendto);
void (*BotGetChatMessage)(int chatstate, char *buf, int size);
int (*StringContains)(char *str1, char *str2, int casesensitive);
int (*BotFindMatch)(char *str, struct bot_match_s *match, unsigned long int context);
void (*BotMatchVariable)(struct bot_match_s *match, int variable, char *buf, int size);
void (*UnifyWhiteSpaces)(char *string);
void (*BotReplaceSynonyms)(char *string, unsigned long int context);
int (*BotLoadChatFile)(int chatstate, char *chatfile, char *chatname);
void (*BotSetChatGender)(int chatstate, int gender);
void (*BotSetChatName)(int chatstate, char *name, int client);
//-----------------------------------
// be_ai_goal.h
//-----------------------------------
void (*BotResetGoalState)(int goalstate);
void (*BotResetAvoidGoals)(int goalstate);
void (*BotRemoveFromAvoidGoals)(int goalstate, int number);
void (*BotPushGoal)(int goalstate, struct bot_goal_s *goal);
void (*BotPopGoal)(int goalstate);
void (*BotEmptyGoalStack)(int goalstate);
void (*BotDumpAvoidGoals)(int goalstate);
void (*BotDumpGoalStack)(int goalstate);
void (*BotGoalName)(int number, char *name, int size);
int (*BotGetTopGoal)(int goalstate, struct bot_goal_s *goal);
int (*BotGetSecondGoal)(int goalstate, struct bot_goal_s *goal);
int (*BotChooseLTGItem)(int goalstate, vec3_t origin, int *inventory, int travelflags);
int (*BotChooseNBGItem)(int goalstate, vec3_t origin, int *inventory, int travelflags,
struct bot_goal_s *ltg, float maxtime);
int (*BotTouchingGoal)(vec3_t origin, struct bot_goal_s *goal);
int (*BotItemGoalInVisButNotVisible)(int viewer, vec3_t eye, vec3_t viewangles, struct bot_goal_s *goal);
int (*BotGetLevelItemGoal)(int index, char *classname, struct bot_goal_s *goal);
int (*BotGetNextCampSpotGoal)(int num, struct bot_goal_s *goal);
int (*BotGetMapLocationGoal)(char *name, struct bot_goal_s *goal);
float (*BotAvoidGoalTime)(int goalstate, int number);
void (*BotSetAvoidGoalTime)(int goalstate, int number, float avoidtime);
void (*BotInitLevelItems)(void);
void (*BotUpdateEntityItems)(void);
int (*BotLoadItemWeights)(int goalstate, char *filename);
void (*BotFreeItemWeights)(int goalstate);
void (*BotInterbreedGoalFuzzyLogic)(int parent1, int parent2, int child);
void (*BotSaveGoalFuzzyLogic)(int goalstate, char *filename);
void (*BotMutateGoalFuzzyLogic)(int goalstate, float range);
int (*BotAllocGoalState)(int client);
void (*BotFreeGoalState)(int handle);
//-----------------------------------
// be_ai_move.h
//-----------------------------------
void (*BotResetMoveState)(int movestate);
void (*BotMoveToGoal)(struct bot_moveresult_s *result, int movestate, struct bot_goal_s *goal, int travelflags);
int (*BotMoveInDirection)(int movestate, vec3_t dir, float speed, int type);
void (*BotResetAvoidReach)(int movestate);
void (*BotResetLastAvoidReach)(int movestate);
int (*BotReachabilityArea)(vec3_t origin, int testground);
int (*BotMovementViewTarget)(int movestate, struct bot_goal_s *goal, int travelflags, float lookahead, vec3_t target);
int (*BotPredictVisiblePosition)(vec3_t origin, int areanum, struct bot_goal_s *goal, int travelflags, vec3_t target);
int (*BotAllocMoveState)(void);
void (*BotFreeMoveState)(int handle);
void (*BotInitMoveState)(int handle, struct bot_initmove_s *initmove);
void (*BotAddAvoidSpot)(int movestate, vec3_t origin, float radius, int type);
//-----------------------------------
// be_ai_weap.h
//-----------------------------------
int (*BotChooseBestFightWeapon)(int weaponstate, int *inventory);
void (*BotGetWeaponInfo)(int weaponstate, int weapon, struct weaponinfo_s *weaponinfo);
int (*BotLoadWeaponWeights)(int weaponstate, char *filename);
int (*BotAllocWeaponState)(void);
void (*BotFreeWeaponState)(int weaponstate);
void (*BotResetWeaponState)(int weaponstate);
//-----------------------------------
// be_ai_gen.h
//-----------------------------------
int (*GeneticParentsAndChildSelection)(int numranks, float *ranks, int *parent1, int *parent2, int *child);
} ai_export_t;
//bot AI library imported functions
typedef struct botlib_export_s
{
//Area Awareness System functions
aas_export_t aas;
//Elementary Action functions
ea_export_t ea;
//AI functions
ai_export_t ai;
//setup the bot library, returns BLERR_
int (*BotLibSetup)(void);
//shutdown the bot library, returns BLERR_
int (*BotLibShutdown)(void);
//sets a library variable returns BLERR_
int (*BotLibVarSet)(char *var_name, char *value);
//gets a library variable returns BLERR_
int (*BotLibVarGet)(char *var_name, char *value, int size);
//sets a C-like define returns BLERR_
int (*PC_AddGlobalDefine)(char *string);
int (*PC_LoadSourceHandle)(const char *filename);
int (*PC_FreeSourceHandle)(int handle);
int (*PC_ReadTokenHandle)(int handle, pc_token_t *pc_token);
int (*PC_SourceFileAndLine)(int handle, char *filename, int *line);
int (*PC_LoadGlobalDefines)(const char* filename );
void (*PC_RemoveAllGlobalDefines) ( void );
//start a frame in the bot library
int (*BotLibStartFrame)(float time);
//load a new map in the bot library
int (*BotLibLoadMap)(const char *mapname);
//entity updates
int (*BotLibUpdateEntity)(int ent, bot_entitystate_t *state);
//just for testing
int (*Test)(int parm0, char *parm1, vec3_t parm2, vec3_t parm3);
} botlib_export_t;
//linking of bot library
botlib_export_t *GetBotLibAPI( int apiVersion, botlib_import_t *import );
/* Library variables:
name: default: module(s): description:
"basedir" "" l_utils.c base directory
"gamedir" "" l_utils.c game directory
"cddir" "" l_utils.c CD directory
"log" "0" l_log.c enable/disable creating a log file
"maxclients" "4" be_interface.c maximum number of clients
"maxentities" "1024" be_interface.c maximum number of entities
"bot_developer" "0" be_interface.c bot developer mode
"phys_friction" "6" be_aas_move.c ground friction
"phys_stopspeed" "100" be_aas_move.c stop speed
"phys_gravity" "800" be_aas_move.c gravity value
"phys_waterfriction" "1" be_aas_move.c water friction
"phys_watergravity" "400" be_aas_move.c gravity in water
"phys_maxvelocity" "320" be_aas_move.c maximum velocity
"phys_maxwalkvelocity" "320" be_aas_move.c maximum walk velocity
"phys_maxcrouchvelocity" "100" be_aas_move.c maximum crouch velocity
"phys_maxswimvelocity" "150" be_aas_move.c maximum swim velocity
"phys_walkaccelerate" "10" be_aas_move.c walk acceleration
"phys_airaccelerate" "1" be_aas_move.c air acceleration
"phys_swimaccelerate" "4" be_aas_move.c swim acceleration
"phys_maxstep" "18" be_aas_move.c maximum step height
"phys_maxsteepness" "0.7" be_aas_move.c maximum floor steepness
"phys_maxbarrier" "32" be_aas_move.c maximum barrier height
"phys_maxwaterjump" "19" be_aas_move.c maximum waterjump height
"phys_jumpvel" "270" be_aas_move.c jump z velocity
"phys_falldelta5" "40" be_aas_move.c
"phys_falldelta10" "60" be_aas_move.c
"rs_waterjump" "400" be_aas_move.c
"rs_teleport" "50" be_aas_move.c
"rs_barrierjump" "100" be_aas_move.c
"rs_startcrouch" "300" be_aas_move.c
"rs_startgrapple" "500" be_aas_move.c
"rs_startwalkoffledge" "70" be_aas_move.c
"rs_startjump" "300" be_aas_move.c
"rs_rocketjump" "500" be_aas_move.c
"rs_bfgjump" "500" be_aas_move.c
"rs_jumppad" "250" be_aas_move.c
"rs_aircontrolledjumppad" "300" be_aas_move.c
"rs_funcbob" "300" be_aas_move.c
"rs_startelevator" "50" be_aas_move.c
"rs_falldamage5" "300" be_aas_move.c
"rs_falldamage10" "500" be_aas_move.c
"rs_maxjumpfallheight" "450" be_aas_move.c
"max_aaslinks" "4096" be_aas_sample.c maximum links in the AAS
"max_routingcache" "4096" be_aas_route.c maximum routing cache size in KB
"forceclustering" "0" be_aas_main.c force recalculation of clusters
"forcereachability" "0" be_aas_main.c force recalculation of reachabilities
"forcewrite" "0" be_aas_main.c force writing of aas file
"aasoptimize" "0" be_aas_main.c enable aas optimization
"sv_mapChecksum" "0" be_aas_main.c BSP file checksum
"bot_visualizejumppads" "0" be_aas_reach.c visualize jump pads
"bot_reloadcharacters" "0" - reload bot character files
"ai_gametype" "0" be_ai_goal.c game type
"droppedweight" "1000" be_ai_goal.c additional dropped item weight
"weapindex_rocketlauncher" "5" be_ai_move.c rl weapon index for rocket jumping
"weapindex_bfg10k" "9" be_ai_move.c bfg weapon index for bfg jumping
"weapindex_grapple" "10" be_ai_move.c grapple weapon index for grappling
"entitytypemissile" "3" be_ai_move.c ET_MISSILE
"offhandgrapple" "0" be_ai_move.c enable off hand grapple hook
"cmd_grappleon" "grappleon" be_ai_move.c command to activate off hand grapple
"cmd_grappleoff" "grappleoff" be_ai_move.c command to deactivate off hand grapple
"itemconfig" "items.c" be_ai_goal.c item configuration file
"weaponconfig" "weapons.c" be_ai_weap.c weapon configuration file
"synfile" "syn.c" be_ai_chat.c file with synonyms
"rndfile" "rnd.c" be_ai_chat.c file with random strings
"matchfile" "match.c" be_ai_chat.c file with match strings
"nochat" "0" be_ai_chat.c disable chats
"max_messages" "1024" be_ai_chat.c console message heap size
"max_weaponinfo" "32" be_ai_weap.c maximum number of weapon info
"max_projectileinfo" "32" be_ai_weap.c maximum number of projectile info
"max_iteminfo" "256" be_ai_goal.c maximum number of item info
"max_levelitems" "256" be_ai_goal.c maximum number of level items
*/

124
code/game/chars.h Normal file
View File

@ -0,0 +1,124 @@
// Copyright (C) 2001-2002 Raven Software
//
//===========================================================================
//
// Name: chars.h
// Function: bot characteristics
// Programmer: Mr Elusive (MrElusive@idsoftware.com)
// Last update: 1999-09-08
// Tab Size: 4 (real tabs)
//===========================================================================
//========================================================
//========================================================
//name
#define CHARACTERISTIC_NAME 0 //string
//gender of the bot
#define CHARACTERISTIC_GENDER 1 //string ("male", "female", "it")
//attack skill
// > 0.0 && < 0.2 = don't move
// > 0.3 && < 1.0 = aim at enemy during retreat
// > 0.0 && < 0.4 = only move forward/backward
// >= 0.4 && < 1.0 = circle strafing
// > 0.7 && < 1.0 = random strafe direction change
#define CHARACTERISTIC_ATTACK_SKILL 2 //float [0, 1]
//weapon weight file
#define CHARACTERISTIC_WEAPONWEIGHTS 3 //string
//view angle difference to angle change factor
#define CHARACTERISTIC_VIEW_FACTOR 4 //float <0, 1]
//maximum view angle change
#define CHARACTERISTIC_VIEW_MAXCHANGE 5 //float [1, 360]
//reaction time in seconds
#define CHARACTERISTIC_REACTIONTIME 6 //float [0, 5]
//accuracy when aiming
#define CHARACTERISTIC_AIM_ACCURACY 7 //float [0, 1]
//weapon specific aim accuracy
#define CHARACTERISTIC_AIM_ACCURACY_MACHINEGUN 8 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_SHOTGUN 9 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_ROCKETLAUNCHER 10 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_GRENADELAUNCHER 11 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_LIGHTNING 12
#define CHARACTERISTIC_AIM_ACCURACY_PLASMAGUN 13 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_RAILGUN 14
#define CHARACTERISTIC_AIM_ACCURACY_BFG10K 15 //float [0, 1]
//skill when aiming
// > 0.0 && < 0.9 = aim is affected by enemy movement
// > 0.4 && <= 0.8 = enemy linear leading
// > 0.8 && <= 1.0 = enemy exact movement leading
// > 0.5 && <= 1.0 = prediction shots when enemy is not visible
// > 0.6 && <= 1.0 = splash damage by shooting nearby geometry
#define CHARACTERISTIC_AIM_SKILL 16 //float [0, 1]
//weapon specific aim skill
#define CHARACTERISTIC_AIM_SKILL_ROCKETLAUNCHER 17 //float [0, 1]
#define CHARACTERISTIC_AIM_SKILL_GRENADELAUNCHER 18 //float [0, 1]
#define CHARACTERISTIC_AIM_SKILL_PLASMAGUN 19 //float [0, 1]
#define CHARACTERISTIC_AIM_SKILL_BFG10K 20 //float [0, 1]
//========================================================
//chat
//========================================================
//file with chats
#define CHARACTERISTIC_CHAT_FILE 21 //string
//name of the chat character
#define CHARACTERISTIC_CHAT_NAME 22 //string
//characters per minute type speed
#define CHARACTERISTIC_CHAT_CPM 23 //integer [1, 4000]
//tendency to insult/praise
#define CHARACTERISTIC_CHAT_INSULT 24 //float [0, 1]
//tendency to chat misc
#define CHARACTERISTIC_CHAT_MISC 25 //float [0, 1]
//tendency to chat at start or end of level
#define CHARACTERISTIC_CHAT_STARTENDLEVEL 26 //float [0, 1]
//tendency to chat entering or exiting the game
#define CHARACTERISTIC_CHAT_ENTEREXITGAME 27 //float [0, 1]
//tendency to chat when killed someone
#define CHARACTERISTIC_CHAT_KILL 28 //float [0, 1]
//tendency to chat when died
#define CHARACTERISTIC_CHAT_DEATH 29 //float [0, 1]
//tendency to chat when enemy suicides
#define CHARACTERISTIC_CHAT_ENEMYSUICIDE 30 //float [0, 1]
//tendency to chat when hit while talking
#define CHARACTERISTIC_CHAT_HITTALKING 31 //float [0, 1]
//tendency to chat when bot was hit but didn't dye
#define CHARACTERISTIC_CHAT_HITNODEATH 32 //float [0, 1]
//tendency to chat when bot hit the enemy but enemy didn't dye
#define CHARACTERISTIC_CHAT_HITNOKILL 33 //float [0, 1]
//tendency to randomly chat
#define CHARACTERISTIC_CHAT_RANDOM 34 //float [0, 1]
//tendency to reply
#define CHARACTERISTIC_CHAT_REPLY 35 //float [0, 1]
//========================================================
//movement
//========================================================
//tendency to crouch
#define CHARACTERISTIC_CROUCHER 36 //float [0, 1]
//tendency to jump
#define CHARACTERISTIC_JUMPER 37 //float [0, 1]
//tendency to walk
#define CHARACTERISTIC_WALKER 48 //float [0, 1]
//tendency to jump using a weapon
#define CHARACTERISTIC_WEAPONJUMPING 38 //float [0, 1]
//tendency to use the grapple hook when available
#define CHARACTERISTIC_GRAPPLE_USER 39 //float [0, 1] //use this!!
//========================================================
//goal
//========================================================
//item weight file
#define CHARACTERISTIC_ITEMWEIGHTS 40 //string
//the aggression of the bot
#define CHARACTERISTIC_AGGRESSION 41 //float [0, 1]
//the self preservation of the bot (rockets near walls etc.)
#define CHARACTERISTIC_SELFPRESERVATION 42 //float [0, 1]
//how likely the bot is to take revenge
#define CHARACTERISTIC_VENGEFULNESS 43 //float [0, 1] //use this!!
//tendency to camp
#define CHARACTERISTIC_CAMPER 44 //float [0, 1]
//========================================================
//========================================================
//tendency to get easy frags
#define CHARACTERISTIC_EASY_FRAGGER 45 //float [0, 1]
//how alert the bot is (view distance)
#define CHARACTERISTIC_ALERTNESS 46 //float [0, 1]
//how much the bot fires it's weapon
#define CHARACTERISTIC_FIRETHROTTLE 47 //float [0, 1]

1404
code/game/g_active.c Normal file

File diff suppressed because it is too large Load Diff

319
code/game/g_antilag.c Normal file
View File

@ -0,0 +1,319 @@
// Copyright (C) 2000-2001 Raven Software, Inc.
//
// g_antilag.c -- handles server side anti-lag
#include "g_local.h"
/*
================
G_UpdateClientAntiLag
================
*/
void G_UpdateClientAntiLag ( gentity_t* ent )
{
int head;
int newtime;
head = ent->client->antilagHead;
// If on a new frame snap the head up to the end of the last frame and
// add a new head
if ( ent->client->antilag[head].leveltime < level.time )
{
ent->client->antilag[head].time = level.previousTime;
// Move to the next position
if ( (++ent->client->antilagHead) > MAX_ANTILAG )
{
ent->client->antilagHead = 0;
}
head = ent->client->antilagHead;
}
// Bots only move once per frame
if ( ent->r.svFlags & SVF_BOT )
{
newtime = level.time;
}
else
{
// calculate the actual server time
newtime = level.previousTime + trap_Milliseconds() - level.frameStartTime;
if ( newtime > level.time )
{
newtime = level.time;
}
else if ( newtime <= level.previousTime )
{
newtime = level.previousTime + 1;
}
}
// Copy the clients current state into the antilag cache
ent->client->antilag[head].leveltime = level.time;
ent->client->antilag[head].time = newtime;
VectorCopy ( ent->r.currentOrigin, ent->client->antilag[head].rOrigin );
VectorCopy ( ent->r.currentAngles, ent->client->antilag[head].rAngles );
VectorCopy ( ent->r.mins, ent->client->antilag[head].mins );
VectorCopy ( ent->r.maxs, ent->client->antilag[head].maxs );
VectorCopy ( ent->client->ghoulLegsAngles, ent->client->antilag[head].legsAngles );
VectorCopy ( ent->client->ghoulLowerTorsoAngles, ent->client->antilag[head].lowerTorsoAngles );
VectorCopy ( ent->client->ghoulUpperTorsoAngles, ent->client->antilag[head].upperTorsoAngles );
VectorCopy ( ent->client->ghoulHeadAngles, ent->client->antilag[head].headAngles );
ent->client->antilag[head].legsAnim = ent->s.legsAnim;
ent->client->antilag[head].torsoAnim = ent->s.torsoAnim;
ent->client->antilag[head].pm_flags = ent->client->ps.pm_flags;
ent->client->antilag[head].leanTime = ent->client->ps.leanTime;
}
/*
================
G_UndoClientAntiLag
================
*/
void G_UndoClientAntiLag ( gentity_t* ent )
{
// If the client isnt already in the past then
// dont bother doing anything
if ( ent->client->antilagUndo.leveltime != level.time )
return;
// Move the client back into reality by moving over the undo information
VectorCopy ( ent->client->antilagUndo.rOrigin, ent->r.currentOrigin );
VectorCopy ( ent->client->antilagUndo.rAngles, ent->r.currentAngles );
VectorCopy ( ent->client->antilagUndo.mins, ent->r.mins );
VectorCopy ( ent->client->antilagUndo.maxs, ent->r.maxs );
VectorCopy ( ent->client->antilagUndo.legsAngles, ent->client->ghoulLegsAngles );
VectorCopy ( ent->client->antilagUndo.lowerTorsoAngles, ent->client->ghoulLowerTorsoAngles );
VectorCopy ( ent->client->antilagUndo.upperTorsoAngles, ent->client->ghoulUpperTorsoAngles );
VectorCopy ( ent->client->antilagUndo.headAngles, ent->client->ghoulHeadAngles );
ent->s.legsAnim = ent->client->antilagUndo.legsAnim;
ent->s.torsoAnim = ent->client->antilagUndo.torsoAnim;
ent->client->ps.pm_flags = ent->client->antilagUndo.pm_flags;
ent->client->ps.leanTime = ent->client->antilagUndo.leanTime;
// Mark the undo information so it cant be used again
ent->client->antilagUndo.leveltime = 0;
}
/*
================
G_ApplyClientAntiLag
================
*/
void G_ApplyClientAntiLag ( gentity_t* ent, int time )
{
float lerp;
int from;
int to;
// Find the two pieces of history information that sandwitch the
// time we are looking for
from = ent->client->antilagHead;
to = ent->client->antilagHead;
do
{
if ( ent->client->antilag[from].time <= time )
{
break;
}
to = from;
from--;
if ( from < 0 )
{
from = MAX_ANTILAG - 1;
}
}
while ( from != ent->client->antilagHead );
// If the from is equal to the to then there wasnt even
// one piece of information worth using so just use the current time frame
if ( from == to )
{
return;
}
// Save the undo information if its not already saved
if ( ent->client->antilagUndo.leveltime != level.time )
{
// Save the undo information
ent->client->antilagUndo.leveltime = level.time;
VectorCopy ( ent->r.currentOrigin, ent->client->antilagUndo.rOrigin );
VectorCopy ( ent->r.currentAngles, ent->client->antilagUndo.rAngles );
VectorCopy ( ent->r.mins, ent->client->antilagUndo.mins );
VectorCopy ( ent->r.maxs, ent->client->antilagUndo.maxs );
VectorCopy ( ent->client->ghoulLegsAngles, ent->client->antilagUndo.legsAngles );
VectorCopy ( ent->client->ghoulLowerTorsoAngles, ent->client->antilagUndo.lowerTorsoAngles );
VectorCopy ( ent->client->ghoulUpperTorsoAngles, ent->client->antilagUndo.upperTorsoAngles );
VectorCopy ( ent->client->ghoulHeadAngles, ent->client->antilagUndo.headAngles );
ent->client->antilagUndo.legsAnim = ent->s.legsAnim;
ent->client->antilagUndo.torsoAnim = ent->s.torsoAnim;
ent->client->antilagUndo.pm_flags = ent->client->ps.pm_flags;
ent->client->antilagUndo.leanTime = ent->client->ps.leanTime;
}
// If the best history found was the last in the list then
// dont lerp, just use the last one
if ( from == ent->client->antilagHead )
{
VectorCopy ( ent->client->antilag[to].rOrigin, ent->r.currentOrigin );
VectorCopy ( ent->client->antilag[to].rAngles, ent->r.currentAngles );
VectorCopy ( ent->client->antilag[to].mins, ent->r.maxs );
VectorCopy ( ent->client->antilag[to].maxs, ent->r.mins );
VectorCopy ( ent->client->antilag[to].legsAngles, ent->client->ghoulLegsAngles );
VectorCopy ( ent->client->antilag[to].lowerTorsoAngles, ent->client->ghoulLowerTorsoAngles );
VectorCopy ( ent->client->antilag[to].upperTorsoAngles, ent->client->ghoulUpperTorsoAngles );
VectorCopy ( ent->client->antilag[to].headAngles, ent->client->ghoulHeadAngles );
ent->s.legsAnim = ent->client->antilag[to].legsAnim;
ent->s.torsoAnim = ent->client->antilag[to].torsoAnim;
ent->client->ps.pm_flags = ent->client->antilag[to].pm_flags;
ent->client->ps.leanTime = ent->client->antilag[to].leanTime;
}
else
{
// Calculate the lerp value to use for the vectors
lerp = (float)(time - ent->client->antilag[from].time) / (float)(ent->client->antilag[to].time - ent->client->antilag[from].time);
// Lerp all the vectors between the before and after history information
LerpVector ( ent->client->antilag[from].rOrigin, ent->client->antilag[to].rOrigin, lerp, ent->r.currentOrigin );
LerpVector ( ent->client->antilag[from].rAngles, ent->client->antilag[to].rAngles, lerp, ent->r.currentAngles );
LerpVector ( ent->client->antilag[from].maxs, ent->client->antilag[to].maxs, lerp, ent->r.maxs );
LerpVector ( ent->client->antilag[from].mins, ent->client->antilag[to].mins, lerp, ent->r.mins );
LerpVector ( ent->client->antilag[from].legsAngles, ent->client->antilag[to].legsAngles, lerp, ent->client->ghoulLegsAngles );
LerpVector ( ent->client->antilag[from].lowerTorsoAngles, ent->client->antilag[to].lowerTorsoAngles, lerp, ent->client->ghoulLowerTorsoAngles );
LerpVector ( ent->client->antilag[from].upperTorsoAngles, ent->client->antilag[to].upperTorsoAngles, lerp, ent->client->ghoulUpperTorsoAngles );
LerpVector ( ent->client->antilag[from].headAngles, ent->client->antilag[to].headAngles, lerp, ent->client->ghoulHeadAngles );
ent->client->ps.leanTime = ent->client->antilag[from].leanTime + (ent->client->antilag[from].leanTime-ent->client->antilag[to].leanTime) * lerp;
ent->s.legsAnim = ent->client->antilag[to].legsAnim;
ent->s.torsoAnim = ent->client->antilag[to].torsoAnim;
ent->client->ps.pm_flags = ent->client->antilag[to].pm_flags;
}
}
/*
================
G_UndoAntiLag
================
*/
void G_UndoAntiLag ( void )
{
int i;
// Undo all history
for ( i = 0; i < level.numConnectedClients; i ++ )
{
gentity_t* other = &g_entities[level.sortedClients[i]];
if ( other->client->pers.connected != CON_CONNECTED )
{
continue;
}
// Skip clients that are spectating
if ( G_IsClientSpectating ( other->client ) || G_IsClientDead ( other->client ) )
{
continue;
}
if ( other->r.svFlags & SVF_DOUBLED_BBOX )
{
// Put the hitbox back the way it was
other->r.maxs[0] /= 2;
other->r.maxs[1] /= 2;
other->r.mins[0] /= 2;
other->r.mins[1] /= 2;
other->r.svFlags &= (~SVF_DOUBLED_BBOX);
}
G_UndoClientAntiLag ( other );
// Relink the entity into the world
trap_LinkEntity ( other );
}
}
/*
================
G_ApplyAntiLag
================
*/
void G_ApplyAntiLag ( gentity_t* ref, qboolean enlargeHitBox )
{
int i;
int reftime;
// Figure out the reference time based on the reference clients server time
reftime = ref->client->pers.cmd.serverTime;
if ( reftime > level.time )
{
reftime = level.time;
}
// Move all the clients back into the reference clients time frame.
for ( i = 0; i < level.numConnectedClients; i ++ )
{
gentity_t* other = &g_entities[level.sortedClients[i]];
if ( other->client->pers.connected != CON_CONNECTED )
{
continue;
}
// Skip the reference client
if ( other == ref )
{
continue;
}
// Skip entities not in use
if ( !other->inuse )
{
continue;
}
// Skip clients that are spectating
if ( G_IsClientSpectating ( other->client ) || G_IsClientDead ( other->client ) )
{
continue;
}
// Dont bring them back in time unless requested
if ( !(ref->r.svFlags & SVF_BOT) & ref->client->pers.antiLag )
{
// Apply the antilag to this player
G_ApplyClientAntiLag ( other, reftime );
}
if ( enlargeHitBox )
{
// Adjust the hit box to account for hands and such
// that are sticking out of the normal bounding box
other->r.maxs[0] *= 2;
other->r.maxs[1] *= 2;
other->r.mins[0] *= 2;
other->r.mins[1] *= 2;
other->r.svFlags |= SVF_DOUBLED_BBOX;
}
// Relink the entity into the world
trap_LinkEntity ( other );
}
}

1082
code/game/g_bot.c Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More