2007-06-14

This commit is contained in:
Anonymous Maarten 2015-12-03 01:38:22 +01:00
parent e20673c2cd
commit 1ae34ae340
96 changed files with 5680 additions and 1020 deletions

52
ai.cpp Normal file
View File

@ -0,0 +1,52 @@
#include <cassert>
#include "ai.h"
#include "opengta.h"
#include "game_objects.h"
#include "cell_iterator.h"
#include "log.h"
namespace OpenGTA {
namespace AI {
namespace Pedestrian {
void walk_pavement(OpenGTA::Pedestrian* ped) {
assert(ped);
Util::CellIterator ci(ped->pos);
if (!ci.isValid())
return;
OpenGTA::Map::BlockInfo & bi = ci.getBlock();
//INFO << " ped in bt: " << int(bi.blockType()) << std::endl;
//INFO << ped->pos.x << " " << ped->pos.z << std::endl;
std::pair<bool, Util::CellIterator> f = ci.findNeighbourWithType(3, ped->rot);
if (f.first) {
//INFO << "next: " << f.second.x << " " << f.second.y << std::endl;
ped->aiData.pos1 = Vector3D(f.second.x+0.5f, ped->pos.y, f.second.y+0.5f);
ped->aiMode = 1;
}
}
void moveto_shortrange(OpenGTA::Pedestrian *ped) {
assert(ped);
float d = Util::distance(ped->pos, ped->aiData.pos1);
//INFO << "dist: " << d << std::endl;
float a = Util::xz_turn_angle(ped->pos, ped->aiData.pos1);
float da = Util::xz_angle(ped->pos, ped->aiData.pos1);
//INFO << a << std::endl;
//INFO << "rot " << ped->rot << std::endl;
ped->m_control.setMoveForward(false);
ped->m_control.setTurnLeft(false);
ped->m_control.setTurnRight(false);
//INFO << ped->rot + a << std::endl;
if (fabs(ped->rot - da) > 5) {
if (a > 0)
ped->m_control.setTurnLeft(true);
else
ped->m_control.setTurnRight(true);
}
if (fabs(ped->rot - da) < 120 && d > 0.19f)
ped->m_control.setMoveForward(true);
if (d <= 0.19f)
ped->aiMode = 0;
}
}
}
}

16
ai.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef OGTA_AI_H
#define OGTA_AI_H
namespace OpenGTA {
class Pedestrian;
namespace AI {
namespace Pedestrian {
void walk_pavement(OpenGTA::Pedestrian*);
void moveto_shortrange(OpenGTA::Pedestrian*);
void move_away(OpenGTA::Pedestrian*);
}
}
}
#endif

View File

@ -39,9 +39,9 @@ namespace OpenGTA {
Loki::DefaultLifetime, Loki::SingleThreaded> BlockDataHolder; Loki::DefaultLifetime, Loki::SingleThreaded> BlockDataHolder;
} }
#define SLOPE_RAW_DATA BlockDataHolder::Instance().slope_raw_data #define SLOPE_RAW_DATA OpenGTA::BlockDataHolder::Instance().slope_raw_data
#define SLOPE_TEX_DATA BlockDataHolder::Instance().slope_tex_data #define SLOPE_TEX_DATA OpenGTA::BlockDataHolder::Instance().slope_tex_data
#define LID_NORMAL_DATA BlockDataHolder::Instance().lid_normal_data #define LID_NORMAL_DATA OpenGTA::BlockDataHolder::Instance().lid_normal_data
#endif #endif

View File

@ -1,19 +1,72 @@
Bug: style001.gry bridge texture artifacts Bug: style001.gry bridge texture artifacts
Image: http://skybound.portland.co.uk/ogta/bugs_in_transparent_texture_2006-10-03.jpg Image: http://picasaweb.google.com/under.northern.sky/OpenGTAScreenshots/photo#5015284379944604402
black pixel inside a side texture (nyc.cmp)... thus begins the black pixel inside a side texture (nyc.cmp)... thus begins the
'how many errors can there be about black vs. transparent contest'. 'how many errors can there be about black vs. transparent contest'.
%% %%
Bug: wrong block texture coords Bug: wrong block texture coords
Image: http://lh6.google.com/image/under.northern.sky/RZnek0op0yI/AAAAAAAAAB4/zfCFvPS8gWg/still_slope_tex_errors_2007-01-01.jpg Image: http://picasaweb.google.com/under.northern.sky/OpenGTAScreenshots/photo#5015284384239571746
Status: maybe-closed
Most likely the side that is a triangle and not a quad. Most likely the side that is a triangle and not a quad.
Needs research if 'flipping' the texture is related. Needs research if 'flipping' the texture is related.
Update: fixed for the case shown in the screenshot; may lurk on north/south sides of
blocks, flipping/rotation influence remains unknown.
%% %%
Bug: transparent pixel in g24 tiles Bug: transparent pixel in g24 tiles
Image: http://lh4.google.com/image/under.northern.sky/Rh58SCRd8kI/AAAAAAAAAEQ/FK6KLriTfOs/nyc_gry_block_transparent_pixel_bug_2007-04-12.jpg Image: http://picasaweb.google.com/under.northern.sky/OpenGTAScreenshots/photo#5052612481245901378
Those should probably just be black. It is not a very obvious Those should probably just be black. It is not a very obvious
error, but it should be fixed. error, but it should be fixed.
%% %%
Bug: black border around sprites Bug: black border around sprites
Image: http://lh4.google.com/image/under.northern.sky/Rh58SCRd8lI/AAAAAAAAAEY/tnMwSk8IVok/g24_obj_black_border_2007-04-12.jpg Image: http://picasaweb.google.com/under.northern.sky/OpenGTAScreenshots/photo#5052612481245901394
Simply doesn't look good, especially with g24 graphics. Simply doesn't look good, especially with g24 graphics.
%% %%
Bug: wrong-player position in viewer.exe when switching from free mode (F4)
A position somewhat ~north~ is actually used; if you are at the north-border of the
city this can cause the player to be spawned outside 0->255 ^2 range, which exits
the program.
%%
Bug: wrong walk/run animations when armed
Switching between forward/backward/run often changes the weapon as well; walking
forward with the gun doesn't work at all.
%%
Bug: scale2x disabled in all previous releases
The script prepare_build.sh defines -DDO_SCALEX while the code actually is
activated by -DDO_SCALE2X; errare humanum est.
This bug will be closed when the next release includes this feature; otherwise
see cvs.
%%
Bug: switching to/from fullscreen (at runtime) is broken on Windows (again?)
Most polygons are plain white, some strange rendering errors appear as well;
aka. oh gl-context, where did all my textures go?
Does this affect switching the screen resolution as well? Probably :-(
%%
Bug: vertical sync - SDL_GL_SWAP_CONTROL
Does not work in the Win32 binaries, the SDL version I used is too old.
Stopped doing anything on at least my Linux system (after an update) as well.
%%
Bug: Data _or_ interpretation - block type
Image: http://picasaweb.google.com/under.northern.sky/OpenGTAScreenshots/photo#5060057403938727394
Several problems may stem from the 'flags stored in block above the one with the graphic' gta-
legacy. The symptom is: you can fall through some floor blocks!
Probably several cases exist; either a bug in my code or some quirk of the map format.
%%
Bug: Collision with 'flat' blocks
Partially transparent blocks (sign posts, fence, etc.) need special rules to handle
blocking of peds/projectiles/car; implemented only for peds.
Furthermore only works on nyc.cmp, need to research the tile-ids for the other style
files.
FIXME: which blocks should _not_ block projectiles?
%%
Bug: Pedestrian movement physics
1) Moving up/down on a slope should influence speed
2) You can walk up a single vertical wall (can be seen when walking on roofs;
probably also teleports to the upper road when under the bridges in nyc.cmp.
%%

View File

@ -93,9 +93,17 @@ void Matrix3D::Translate(const Vector3D & v)
} }
void Matrix3D::RotZ(float angle) { void Matrix3D::RotZ(float angle) {
const float TO_RAD = M_PI / 180.0f; const float c = cosf(angle * M_PI / 180.0f);
const float s = sinf(angle * M_PI / 180.0f);
/*
m[0][0] = cosf(angle*TO_RAD); m[0][0] = cosf(angle*TO_RAD);
m[1][0] = sinf(angle*TO_RAD); m[1][0] = sinf(angle*TO_RAD);
m[0][1] = -sinf(angle*TO_RAD); m[0][1] = -sinf(angle*TO_RAD);
m[1][1] = cosf(angle*TO_RAD); m[1][1] = cosf(angle*TO_RAD);
*/
m[0][0] = c;
m[2][2] = c;
m[0][2] = s;
m[2][0] = -s;
} }

View File

@ -93,11 +93,14 @@ struct Matrix3
}; };
static const Matrix3 Identity; static const Matrix3 Identity;
Vector3D& baseRow(int i) { return *((Vector3D*)m[i]); } //Vector3D& baseRow(int i) { return *((Vector3D*)m[i]); }
float operator() (int i, int j) const { return m[i][j]; } float operator() (int i, int j) const { return m[i][j]; }
float& operator() (int i, int j) { return m[i][j]; } float& operator() (int i, int j) { return m[i][j]; }
}; };
Matrix3D PitchMatrix3D(const float theta);
Matrix3D YawMatrix3D(const float theta);
Matrix3D RollMatrix3D(const float theta);
struct Matrix3D struct Matrix3D
{ {
union { union {
@ -127,9 +130,11 @@ struct Matrix3D
return *this = *this * m; return *this = *this * m;
} }
/*
friend Matrix3D PitchMatrix3D(const float theta); friend Matrix3D PitchMatrix3D(const float theta);
friend Matrix3D YawMatrix3D(const float theta); friend Matrix3D YawMatrix3D(const float theta);
friend Matrix3D RollMatrix3D(const float theta); friend Matrix3D RollMatrix3D(const float theta);
*/
void rotate(const Vector3D& v); void rotate(const Vector3D& v);
Matrix3D Inverse() const; Matrix3D Inverse() const;

134
cvs_changelog.txt Normal file
View File

@ -0,0 +1,134 @@
2007-06-14 skyb
* fixes for win32 build
* updated bugs, documentation, build system
* preparing to change key input handling
2007-05-30 skyb
* added WGL swap interval feature
* spriteplayer: try anim feature; updated docs
* luaviewer: read config file
* experimental parts of in-game gui
* playing around with basic ped ai
* environment variable influences language file
* updated docs; added author of code fragment to license
2007-05-17 skyb
* derived EntityController registers state change
* rotation fixes
* fixes concerning weapons + moving
* car deltas: damage, doors, lights
* more about "shooting" (hit, damage, explode cars);
col-det tries to find angle for peds (still always the same anim)
* fix: choose correct sprType for non-CAR types (bike, bus, train)
* gui: drawing a string right-to-left
* Map::BlockInfo partial setXXX() functionality
* choose fxt language file (not hardcoded to english anymore)
* 'viewer' screen-gamma in game
* updated usage & version info
* code cleanup
2007-04-30 skyb
* updated bugs list; fixed image links
* vsync options: none, sdl, glx
* uses anisotropic texture filtering if extension is supported
* viewer config options for above (and mipmap & scale2x)
* playing around with car-data
* cars block ped movement
2007-04-25 skyb
A number of helpers:
* project housekeeping
* data dumper tool for cars
* fxt <-> txt converter (txt -> fxt partially working)
* build_svg_rect: visually verify Rectangle operations
* raw_image: generate information about gui 2d art
* projectile-wall collisions should now work on all tiles; minus: z-info,
non-blocking ids
* test code for block-type; minimap nows exports several bmps, viewer
shows colored lines
2007-04-23 skyb
* main feature: projectile hits walls; flat case not working correctly
* (partially?) fixed the triangle-slope texture bug; top/bottom sides?
* gui.h/cpp is included, moved code into image_loader for reuse
2007-04-16 skyb
fix: allowing 24 bit color depth
really unimportant fixes
contains the code release date; may not be accurate in cvs but will serve
as a kind of version-number for actual releases.
removing dependency on unused code
* feature: animated block textures
* switching from GL matrix to calculations for obj position
* collision: projectile + pedestrian
* unique id generator
* other helpers (not really used so far)
2007-04-12 skyb
Fixes, cleanup and new helpers... little new features:
* prototype sounds: play fx, play music
* many peds on map, running randomly around player
2007-02-25 skyb
* screen: try to guess color depth from bpp
(fixes hang on < 32 bit x11 displays)
* missing code from last commit
fix: lookup now gets level number; should work for all gta1 maps
* build script should detect if SDL_GL_SWAP_CONTROL is defined (by SDL
>= 1.2.10)
* sdl_init & videomode: check for errors
* sector name from message db
* initial projectile support
* minor game_object updates
2007-02-17 skyb
* abstract_container: return (reference to copy of) added T
* enable weapons selection/animation
* more screen config options
* gui-object cleanup
* file_helper: load vfs into mem (for Lua)
* spriteplayer: update to new version (compiles again) + camera hack
(gravity doubles
as y-scroll switch)
* build-system: config.h instead of -D defines; related changes
* coldet/opensteer in license.txt
2007-02-16 skyb
* each explosion plays once and gets removed
* FIXME: at high framerates there is a visible delay when the textures
aren't loaded
* rewrote spritemanager & game objects
* some other fixes
* assorted helpers; sometimes even with testcase, generally not used at
this time
A first halfway working version; some older features are broken,
it may even compile (right now).
2007-01-09 skyb
Importing src release 2006-12-10
Initial revision

View File

@ -116,6 +116,7 @@ namespace OpenGTA {
template<> void MainMsgLookup::load(const std::string & file) { template<> void MainMsgLookup::load(const std::string & file) {
unload(); unload();
try { try {
INFO << "Trying to load: " << file << std::endl;
m_data = new MessageDB(file); m_data = new MessageDB(file);
} }
catch (const Exception & e) { catch (const Exception & e) {

53
doc/compiling.txt Normal file
View File

@ -0,0 +1,53 @@
= What happens when you call 'make' =
The main makefile checks the env-variable 'HOST';
which is assumed to be "LINUX" or "WIN32", the latter actually being
used to indicate cross-compiling using a mingw-toolchain.
The main makefile checks if the 'Loki'-library is already there;
if not 'wget's it and calls loki.make(.w32_cross) to build it.
It then looks for a file named src_list.make; if that does not exist
it calls "prepare_build.sh $HOST" which generates both src_list.make
and config.h.
The script will only work on Linux where it will use pkg-config to
find the libraries; I hardcoded many Win32 values pointing to my
toolchain and library pathes.
Make now includes src_list.make and builds the default targets;
there are more programs that can be build with an explicit
"make $program_name"; look at src_list.make.
If you need to setup compiler/library paths src_list.make is the
place to do it. Then run make again.
= Features in config.h =
DO_SCALE2X
Enable scale2x algorithm; so far only used for sprites, on if enabled.
HAVE_SDL_VSYNC
Does the SDL header define SDL_GL_SWAP_CONTROL? Must be #undef-ined if
not, may be undefined anyway (turn feature off) and it really depends
whether the driver supports it (at runtime).
In the future a number of WITH_* defines will be used to enable
support for library-dependent features (Lua, SDL_sound + SDL_mixer,
SDL_image). For the moment only the Lua related flag changes 'viewer',
the other features are only used in testcases.
DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT
The initial screen size (unless otherwise defined); defaults to 640x480
if not defined.
DEFAULT_SCREEN_VSYNC
Default setting for vsync;can be one of 0, 1, 2
On Linux you can colorify the log-output by defining LOG_USE_ANSI_COLORS.
= If you modify the code yourself =
Note: the dependency system is somewhat broken, sometimes changes in
header files are ignored; either "make clean" or "touch config.h".

26
doc/ped_remaps.txt Normal file
View File

@ -0,0 +1,26 @@
style001.g24
231 - 293
style002.g24
238 - 300
style003.g24
219 - 281
-------------
1.g24
75 - 131
HK 93
PRIESTS 94
idx: 660
2.g24
79 - 135
HARE KRISHNAS 97
DOCTOR/PRIESTS 98
idx: 662
3.g24
60 - 116
HK 78
PRIESTS 79
idx: 675

173
doc/sprites.txt Normal file
View File

@ -0,0 +1,173 @@
style001.gry
604 - 611 : rotating "x"
612 - 619 : rotating coin
620 - 627 : player, walking
628 - 635 : player, running?
658 - 661 : player, falling?
678 - 689 : player, walking 2?
738 - 745 : player, flame-thrower, standing
746 - 753 : player, flame-thrower, walking
754 - 755 : player, flame-thrower, standing?
756 - 763 : player, gun, standing
764 - 771 : player, gun, running?
772 - 773 : player, gun, standing?
774 - 781 : player, big-gun, standing
782 - 789 : player, big-gun, running?
790 - 791 : player, big-gun, standing?
792 - 796 : player, electro-death
797 - 800 : player, swimming?
801 - 808 : player, punching?
style002.gry
99 - 105 : cone, tumbling
106 - 111 : ring?
112 - 124 : plant?
125 - 129 : road barrier
130 - 136 : road barrier, broken
622 - 629 : player, walking
811 - 818 : cop, walking
819 - 826 : cop, moving?
827 - 844 : cop, driving?
845 - 848 : ???
style001.g24
117 - 127 : smoke, circle, small
128 - 131 : grey bar | dissolving
132 - 135 : red bar | dissolving
136 - 140 : small water splash
141 - 146 : blood dissolving
147 - 150 : brown bar | dissolving
151 - 166 : fire
167 - 173 : big water dissolving
174 : tree
175 - 176: green/grey blob?
188 : box, top open, cross
189 : closed box; x?
190 : box, top open, rockets?
191 : telephone
192 : telephone, arrow
193 : telephone, arrow, highlight
194 : white circle, pickup package
247 - 257 : smoke, right->left, dissolving
258 - 265 : small flames
266 - 273 : water, fire truck
274 - 281 : water hits fire
282 : fire truck part?
283 - 294 : grey smoke, cirle, growing, gets darker
296 - 306 : smoke?, at bottom
307 - 313 : train door open?
315 - 326 : big water splash
327 - 330/331? : fire truck parts
332 - 342 : small smoke (again)
342 - 352 : like above???
354 - 365 : blood grow + dissolve?
366 : big blood splash
367 - 377 : smoke, cone from bottom
393 - 403 : flames, from bottom, flame-thrower?
404 - 411 : rotating canister
412 - 419 : rotating gun
420 - 432 : crate; breaking after first frame
434 - 441 : race finish flag
442 - 454 : crate + stuff; breaking
455 : green blob
456 : red blob
457 - 464 : helicopter blades
465 - 472 : uzi, rotating
473 - 480 : rocket-launcher rotating
481 - 488 : flame-thrower rotating
489 - 496 : red canister rotating
497 - 504 : red ? rotating
506 - 513 : info-sign-post rotating
514 - 521 : blue shield?
522 - 529 : car speed up
530 - 537 : jail free
538 - 545 : extra life
546 - 553 : multiplier up
554 - 561 : police bribe
ped1
second col: (#frames - 1)
0|7|walk
8|7|running forward
16|0|sitting in car
17|7|car exit
25|7|car enter
33|0|sitting in car
34|3|unused junk
38|2|frames, looped while falling
41|0|frame, sliding UNDER car
42|1|frames, usual death pose
44|0|special death pose when shot in back
45|1|played when you get shot in front
47|1|swimming, you CAN swim, but just for 1 cube long
49|0|unknown, most likely not used
50|5|punching while standing animation
56|11|unknown, repeating unused animations
68|9|seems like player strafing? unused.
80|3|jumping onto motorbike
84|0|sitting on a motorbike
85|3|exitting motorbike
89|0|shooting handgun while standing still
91|2|played when you jump onto car
94|0|played while you slide on cars
95|1|played when you drop off a car sliding
97|0|repeated sitting in car
98|0|STANDING COMPLETELY STILL
99|7|walking shooting handgun
107|7|running shooting handgun
115|2|riding a skateboard? unused.
118|7|walking shooting flamethrower
126|7|running shooting flamethrower
134|1|identical standing shooting flamethrower
136|7|walking shooting UZI
144|7|running shooting UZI
152|1|identical standing shooting uzi
154|7|walking shooting rocket launcher
162|7|running shooting rocket launcher
170|1|identical standing shooting rocket launcher
172|4|electrocution by electrified rail
177|3|crawling on floor - unused
181|7|running & punching
police ped
189 - 196 : walking
197 - 204 : running
205 : sitting
206 - 213 : exit car
214 - 221 : enter car
222 : sitting
227 - 228 : falling
229 : slide under
230 : shot front?
231 - 233 : dead? (3 identical frames; lying)
234 : ???
235 : same as 230?
236 - 237 : drowning? different ped colour??
238 : shot in back
239 - 243 : arrest?
269/270? - 272 : enter bike
273 : sitting on bike
274 - 277 : exit bike
278 : standing, gun
278 - 279 : shoot gun?
288 - 292 : electro-death
293 - 294 : shoot uzi

27
doc/using_mods.txt Normal file
View File

@ -0,0 +1,27 @@
Mods can (in theory) be downloaded and used directly
as the ZIP file.
The install procedure in readme.txt is slightly dated,
'viewer' actually does the following:
* look for environment variable "OGTA_DATA"; if it exists
this is used as the base-data source.
By default this is the file 'gtadata.zip' searched in
the current directory (at viewer runtime).
If this source is not valid the directory where viewer
is installed is checked before giving up.
* look for environment variable "OGTA_MOD"; if it exists
and is a valid data-source all files contained within
will overlay files in the base data source.
This is not used by default.
To load a mod I use something like this:
OGTA_MOD=mods/a_mod.zip ./viewer [...] -m map_filename -g style_filename
In this case you have to use -m & -g and use the filenames
contained in the zip (note upper/lower case).
Similiar to gtadata.zip the files have to be in the 'root' of
the ZIP file, not in sub-directory.

View File

@ -41,6 +41,13 @@ namespace OpenGTA {
rawData = v; rawData = v;
} }
bool ControllerWithMemory::statusChanged() {
bool res = (rawData != lastRawData);
if (res)
lastRawData = rawData;
return res;
}
void PedController::setTurnLeft(bool press) { void PedController::setTurnLeft(bool press) {
dataSet.set_item(0, press); dataSet.set_item(0, press);
} }

View File

@ -34,17 +34,31 @@ namespace OpenGTA {
void zero(); void zero();
typedef uint32_t Storage_T; typedef uint32_t Storage_T;
void setRaw(Storage_T v); void setRaw(Storage_T v);
inline const Storage_T & getRaw() { return rawData; }
protected: protected:
EntityController(const EntityController & other); EntityController(const EntityController & other);
Storage_T rawData; Storage_T rawData;
Util::Set dataSet; Util::Set dataSet;
}; };
class ControllerWithMemory : public EntityController {
public:
ControllerWithMemory() : EntityController(),
lastRawData(rawData) {}
ControllerWithMemory(const ControllerWithMemory & o) :
EntityController(o), lastRawData(o.lastRawData) {}
bool statusChanged();
protected:
Storage_T lastRawData;
};
class Pedestrian; class Pedestrian;
class PedController : public EntityController { // class PedController : public EntityController {
class PedController : public ControllerWithMemory {
public: public:
PedController() {} PedController() {}
PedController(const PedController & other) : EntityController(other) {} // PedController(const PedController & other) : EntityController(other) {}
PedController(const PedController & other) : ControllerWithMemory(other) {}
void setTurnLeft(bool press = true); void setTurnLeft(bool press = true);
inline void releaseTurnLeft() { setTurnLeft(false); } inline void releaseTurnLeft() { setTurnLeft(false); }
void setTurnRight(bool press = true); void setTurnRight(bool press = true);

View File

@ -1,31 +1,40 @@
/************************************************************************ /************************************************************************
* Copyright (c) 2005-2007 tok@openlinux.org.uk * * Copyright (c) 2005-2007 tok@openlinux.org.uk *
* * * *
* This software is provided as-is, without any express or implied * * This software is provided as-is, without any express or implied *
* warranty. In no event will the authors be held liable for any * * warranty. In no event will the authors be held liable for any *
* damages arising from the use of this software. * * damages arising from the use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute * * including commercial applications, and to alter it and redistribute *
* it freely, subject to the following restrictions: * * it freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must * * 1. The origin of this software must not be misrepresented; you must *
* not claim that you wrote the original software. If you use this * * not claim that you wrote the original software. If you use this *
* software in a product, an acknowledgment in the product documentation * * software in a product, an acknowledgment in the product documentation *
* would be appreciated but is not required. * * would be appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must * * 2. Altered source versions must be plainly marked as such, and must *
* not be misrepresented as being the original software. * * not be misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source * * 3. This notice may not be removed or altered from any source *
* distribution. * * distribution. *
************************************************************************/ ************************************************************************/
#include "game_objects.h" #include "game_objects.h"
#include "spritemanager.h" #include "spritemanager.h"
#include "dataholder.h" #include "dataholder.h"
#include "cell_iterator.h" #include "cell_iterator.h"
#include "timer.h" #include "timer.h"
#include "Functor.h" #include "Functor.h"
#include "plane.h"
#include "ai.h"
#include "localplayer.h"
// ugly fix for win32
#ifdef WIN32
#undef ERROR
#define ERROR Util::Log::error(__FILE__, __LINE__)
#endif
#define INT2FLOAT_WRLD(c) (float(c >> 6) + float(c % 64) / 64.0f) #define INT2FLOAT_WRLD(c) (float(c >> 6) + float(c % 64) / 64.0f)
#define INT2F_DIV64(v) (float(v) / 64.0f) #define INT2F_DIV64(v) (float(v) / 64.0f)
@ -63,8 +72,10 @@ namespace OpenGTA {
assert(block); assert(block);
if (block->blockType() > 0) { if (block->blockType() > 0) {
float bz = slope_height_offset(block->slopeType(), v.x - x, v.z - z); float bz = slope_height_offset(block->slopeType(), v.x - x, v.z - z);
if (block->slopeType() == 0 && block->blockType() != 5) if (block->slopeType() == 0 && (block->blockType() != 5 &&
block->blockType() != 6))
bz -= 1.0f; bz -= 1.0f;
//INFO << "hit " << int(block->blockType()) << " at " << int(y) << std::endl;
return v.y - (y + bz); return v.y - (y + bz);
} }
y -= 1.0f; y -= 1.0f;
@ -75,8 +86,10 @@ namespace OpenGTA {
assert(block); assert(block);
if (block->blockType() > 0) { if (block->blockType() > 0) {
float bz = slope_height_offset(block->slopeType(), v.x - x, v.z - z); float bz = slope_height_offset(block->slopeType(), v.x - x, v.z - z);
if (block->slopeType() == 0 && block->blockType() != 5) if (block->slopeType() == 0 && (block->blockType() != 5
&& block->blockType() != 6))
bz -= 1.0f; bz -= 1.0f;
//INFO << "hit " << int(block->blockType()) << " at " << int(y) << std::endl;
return v.y - (y + bz); return v.y - (y + bz);
} }
y += 1.0f; y += 1.0f;
@ -130,14 +143,18 @@ namespace OpenGTA {
animId = newId; animId = newId;
} }
uint32_t Pedestrian::fistAmmo = 0;
Pedestrian::Pedestrian(Vector3D e, const Vector3D & p, uint32_t id, Sint16 remapId) : Pedestrian::Pedestrian(Vector3D e, const Vector3D & p, uint32_t id, Sint16 remapId) :
GameObject_common(p), GameObject_common(p),
Sprite(0, remapId, GraphicsBase::SpriteNumbers::PED), Sprite(0, remapId, GraphicsBase::SpriteNumbers::PED),
OBox(TranslateMatrix3D(p), e * 0.5f), OBox(TranslateMatrix3D(p), e * 0.5f),
m_control(), m_control(),
speedForces(0, 0, 0) { speedForces(0, 0, 0),
inventory(), activeWeapon(0), activeAmmo(&fistAmmo),
aiData() {
m_M = TranslateMatrix3D(p); m_M = TranslateMatrix3D(p);
m_M.RotZ(rot); m_M.RotZ(-rot);
pedId = id; pedId = id;
animId = 0; animId = 0;
isDead = 0; isDead = 0;
@ -150,13 +167,17 @@ namespace OpenGTA {
pedId(other.pedId), pedId(other.pedId),
m_control(), m_control(),
speedForces(other.speedForces) { speedForces(other.speedForces),
inventory(other.inventory),
activeWeapon(other.activeWeapon),
activeAmmo(&inventory.find(activeWeapon)->second),
aiData(other.aiData) {
lastUpdateAt = other.lastUpdateAt; lastUpdateAt = other.lastUpdateAt;
inGroundContact = other.inGroundContact; inGroundContact = other.inGroundContact;
animId = other.animId; animId = other.animId;
isDead = other.isDead; isDead = other.isDead;
m_M = TranslateMatrix3D(other.pos); m_M = TranslateMatrix3D(other.pos);
m_M.RotZ(other.rot); m_M.RotZ(-other.rot);
} }
extern void ai_step_fake(Pedestrian*); extern void ai_step_fake(Pedestrian*);
@ -168,26 +189,36 @@ namespace OpenGTA {
} }
if (pedId < 0xffffffff) if (pedId < 0xffffffff)
ai_step_fake(this); ai_step_fake(this);
uint8_t activeWeapon = m_control.getActiveWeapon(); //AI::Pedestrian::walk_pavement(this);
if (aiMode) {
AI::Pedestrian::moveto_shortrange(this);
}
uint8_t chooseWeapon = m_control.getActiveWeapon();
if (chooseWeapon != activeWeapon) {
if (chooseWeapon == 0) {
activeWeapon = 0;
activeAmmo = &fistAmmo;
}
else {
InventoryMap::iterator i = inventory.find(chooseWeapon);
if (i != inventory.end()) {
activeWeapon = chooseWeapon;
activeAmmo = &i->second;
}
}
}
activeWeapon = chooseWeapon;
switch(m_control.getMove()) { switch(m_control.getMove()) {
case 1: case 1:
//if (!(animId == 2u + activeWeapon*3))
// switchToAnim(2 + activeWeapon*3);
if (m_control.getRunning()) { if (m_control.getRunning()) {
if (!(animId == 3u + activeWeapon*3)) if (!(animId == 3u + activeWeapon*3))
switchToAnim(3 + activeWeapon*3); switchToAnim(3 + activeWeapon*3);
} }
else { else {
if (!(animId == 2u + activeWeapon*2)) if (!(animId == 2u + activeWeapon*3))
switchToAnim(2 + activeWeapon*2); switchToAnim(2 + activeWeapon*3);
} }
break; break;
/*
case 2:
if (!(animId == 3u + activeWeapon*3))
switchToAnim(3 + activeWeapon*3);
break;
*/
case 0: case 0:
if (!(animId == 1u + activeWeapon*3)) if (!(animId == 1u + activeWeapon*3))
switchToAnim(1 + activeWeapon*3); switchToAnim(1 + activeWeapon*3);
@ -201,7 +232,7 @@ namespace OpenGTA {
anim.update(ticks); anim.update(ticks);
Uint32 delta = ticks - lastUpdateAt; Uint32 delta = ticks - lastUpdateAt;
//INFO << "delta = " << delta << " t: " << ticks << " lt: " << lastUpdateAt << std::endl; //INFO << "delta = " << delta << " t: " << ticks << " lt: " << lastUpdateAt << std::endl;
Vector3D moveDelta(0, 0, 0); moveDelta = Vector3D(0, 0, 0);
switch(m_control.getTurn()) { switch(m_control.getTurn()) {
case -1: case -1:
rot -= 0.2f * delta; rot -= 0.2f * delta;
@ -234,6 +265,8 @@ namespace OpenGTA {
case 0: case 0:
break; break;
} }
if (pedId == 0xffffffff) {
}
tryMove(pos + moveDelta); tryMove(pos + moveDelta);
if (!inGroundContact) { if (!inGroundContact) {
speedForces.y += 0.0005f *delta; speedForces.y += 0.0005f *delta;
@ -258,6 +291,12 @@ namespace OpenGTA {
SpriteManagerHolder::Instance().createProjectile(0, rot, pos, d1, ticks, pedId); SpriteManagerHolder::Instance().createProjectile(0, rot, pos, d1, ticks, pedId);
lastWeaponTick = ticks; lastWeaponTick = ticks;
} }
/*
if (m_control.statusChanged()) {
INFO << "Ped-event id: " << pedId << " control: " << m_control.getRaw() <<
" time: " << ticks << std::endl;
}*/
//INFO << pos.x << " " << pos.y << " " << pos.z << std::endl; //INFO << pos.x << " " << pos.y << " " << pos.z << std::endl;
lastUpdateAt = ticks; lastUpdateAt = ticks;
} }
@ -271,12 +310,13 @@ namespace OpenGTA {
OpenGTA::GraphicsBase & graphics = OpenGTA::StyleHolder::Instance().get(); OpenGTA::GraphicsBase & graphics = OpenGTA::StyleHolder::Instance().get();
//INFO << heightOverTerrain(nPos) << std::endl; //INFO << heightOverTerrain(nPos) << std::endl;
float hot = heightOverTerrain(nPos); float hot = heightOverTerrain(nPos);
if (hot > 0.1f) if (hot > 0.3f)
inGroundContact = 0; inGroundContact = 0;
else if (hot < 0.0) { else if (hot < 0.0) {
INFO << "gone below: " << hot << " at " << nPos.x << ", " << nPos.y << ", " << nPos.z << std::endl; WARN << "gone below: " << hot << " at " << nPos.x << ", " << nPos.y << ", " << nPos.z << std::endl;
nPos.y -= (hot - 0.3f); nPos.y -= (hot - 0.3f);
INFO << nPos.y << std::endl; //nPos.y += 1;
//INFO << nPos.y << std::endl;
inGroundContact = 1; inGroundContact = 1;
} }
else { else {
@ -287,34 +327,10 @@ namespace OpenGTA {
nPos.y -= hot - 0.1f; nPos.y -= hot - 0.1f;
} }
if (y < map.getNumBlocksAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z)) && y > 0.0f) { if (y < map.getNumBlocksAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z)) && y > 0.0f) {
//INFO << x << ", " << y << ", " << z << ": " << int(map.getNumBlocksAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z))) << std::endl;
OpenGTA::Map::BlockInfo * block = map.getBlockAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z), PHYSFS_uint8(y)); OpenGTA::Map::BlockInfo * block = map.getBlockAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z), PHYSFS_uint8(y));
assert(block);/* assert(block);
if (block->blockType() > 0) { if (block->left && graphics.isBlockingSide(block->left)) {
float bz = slope_height_offset(block->slopeType(), nPos.x - x, nPos.z - z);
if (block->slopeType() == 0)
bz -= 1.0f;
if (inGroundContact) {
nPos.y = y + bz + 0.3f;
//pos = nPos;
}
else if (nPos.y - y - bz < 0.3f) {
INFO << "ped near ground (type: " << int(block->blockType()) << " float-pos: "
<< nPos.x << ", " << nPos.y << ", " << nPos.z << std::endl;
inGroundContact = 1;
nPos.y = y + bz + 0.3f;
INFO << "height rewritten to: " << nPos.y << std::endl;
//pos = nPos;
}
}
else {
inGroundContact = 0;
INFO << "lost footing: " << x << ", " << y << ", " << z << std::endl;
}*/
if (block->left && graphics.isBlockingSide(block->left)) { // && block->isFlat() == false) {
if (block->isFlat()) { if (block->isFlat()) {
//INFO << "xblock left: " << x - pos.x << std::endl;
if (x - pos.x < 0 && x - pos.x > -0.2f) { if (x - pos.x < 0 && x - pos.x > -0.2f) {
nPos.x = (nPos.x < pos.x) ? pos.x : nPos.x; nPos.x = (nPos.x < pos.x) ? pos.x : nPos.x;
} }
@ -341,7 +357,7 @@ namespace OpenGTA {
else if (pos.x - x - 1 < 0 && pos.x - x - 1 > -0.2f) else if (pos.x - x - 1 < 0 && pos.x - x - 1 > -0.2f)
nPos.x = (nPos.x > pos.x) ? pos.x : nPos.x; nPos.x = (nPos.x > pos.x) ? pos.x : nPos.x;
} }
if (block->top && graphics.isBlockingSide(block->top)) { // && block->isFlat() == false) { if (block->top && graphics.isBlockingSide(block->top)) {
if (block->isFlat()) { if (block->isFlat()) {
#ifdef DEBUG_OLD_PED_BLOCK #ifdef DEBUG_OLD_PED_BLOCK
INFO << "zblock top: " << z - pos.z << " tex: " << int(block->top) << std::endl; INFO << "zblock top: " << z - pos.z << " tex: " << int(block->top) << std::endl;
@ -384,7 +400,7 @@ namespace OpenGTA {
} }
if (x < 255 && y < map.getNumBlocksAtNew(PHYSFS_uint8(x+1), PHYSFS_uint8(z))) { if (x < 255 && y < map.getNumBlocksAtNew(PHYSFS_uint8(x+1), PHYSFS_uint8(z))) {
block = map.getBlockAtNew(PHYSFS_uint8(x+1), PHYSFS_uint8(z), PHYSFS_uint8(y)); block = map.getBlockAtNew(PHYSFS_uint8(x+1), PHYSFS_uint8(z), PHYSFS_uint8(y));
if (block->left && graphics.isBlockingSide(block->left)) { // && block->isFlat() == false) { if (block->left && graphics.isBlockingSide(block->left)) {
#ifdef DEBUG_OLD_PED_BLOCK #ifdef DEBUG_OLD_PED_BLOCK
INFO << "xblock left: " << x + 1 - pos.x << " tex: " << int(block->left)<< std::endl; INFO << "xblock left: " << x + 1 - pos.x << " tex: " << int(block->left)<< std::endl;
#endif #endif
@ -411,7 +427,7 @@ namespace OpenGTA {
} }
if (z < 255 && y < map.getNumBlocksAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z+1))) { if (z < 255 && y < map.getNumBlocksAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z+1))) {
block = map.getBlockAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z+1), PHYSFS_uint8(y)); block = map.getBlockAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z+1), PHYSFS_uint8(y));
if (block->top && graphics.isBlockingSide(block->top)) { // && block->isFlat() == false) { if (block->top && graphics.isBlockingSide(block->top)) {
#ifdef DEBUG_OLD_PED_BLOCK #ifdef DEBUG_OLD_PED_BLOCK
INFO << "zblock top: " << z + 1 - pos.z<< " tex: " << int(block->top) << std::endl; INFO << "zblock top: " << z + 1 - pos.z<< " tex: " << int(block->top) << std::endl;
#endif #endif
@ -428,7 +444,15 @@ namespace OpenGTA {
//if (inGroundContact) //if (inGroundContact)
// pos = nPos; // pos = nPos;
} }
if (inGroundContact) bool obj_blocked = false;
std::list<Car> & list = SpriteManagerHolder::Instance().getList<Car>();
for (std::list<Car>::iterator i = list.begin(); i != list.end(); i++) {
if (isBoxInBox(*i)) {
if (Util::distance(pos, i->pos) > Util::distance(nPos, i->pos))
obj_blocked = true;
}
}
if ((inGroundContact) && (obj_blocked == false))
pos = nPos; pos = nPos;
//else //else
// inGroundContact = 0; // inGroundContact = 0;
@ -438,9 +462,17 @@ namespace OpenGTA {
void Pedestrian::die() { void Pedestrian::die() {
INFO << "DIE!!!" << std::endl; INFO << "DIE!!!" << std::endl;
switchToAnim(42); switchToAnim(42);
if (isDead == 3) {
anim.set(Util::Animation::STOPPED, Util::Animation::STOP);
return;
}
anim.set(Util::Animation::PLAY_FORWARD, Util::Animation::FCALLBACK);
Loki::Functor<void> cmd(this, &Pedestrian::die);
anim.setCallback(cmd);
isDead++;
} }
void Pedestrian::getShot(bool front) { void Pedestrian::getShot(uint32_t shooterId, uint32_t dmg, bool front) {
isDead = 1; isDead = 1;
switchToAnim(45); switchToAnim(45);
anim.set(Util::Animation::PLAY_FORWARD, Util::Animation::FCALLBACK); anim.set(Util::Animation::PLAY_FORWARD, Util::Animation::FCALLBACK);
@ -448,33 +480,278 @@ namespace OpenGTA {
anim.setCallback(cmd); anim.setCallback(cmd);
} }
Car::Car(OpenGTA::Map::ObjectPosition& op, uint32_t id) : CarSprite::CarSprite() : sprNum(0), remap(-1),
GameObject_common(Vector3D(INT2FLOAT_WRLD(op.x), 6.05f-INT2FLOAT_WRLD(op.z), INT2FLOAT_WRLD(op.y))), sprType(GraphicsBase::SpriteNumbers::CAR), delta(0),
Sprite(0, -1, GraphicsBase::SpriteNumbers::CAR), OBox(), deltaSet(sizeof(delta) * 8, (unsigned char*)&delta),
carInfo(*StyleHolder::Instance().get().findCarByModel(op.type)){ animState() {}
CarSprite::CarSprite(const CarSprite & o) :
sprNum(o.sprNum), remap(o.remap), sprType(o.sprType), delta(o.delta),
deltaSet(sizeof(delta) * 8, (unsigned char*)&delta),
animState(o.animState) {}
CarSprite::CarSprite(Uint16 sprN, Sint16 rem,
GraphicsBase::SpriteNumbers::SpriteTypes sprT) : sprNum(sprN),
remap(rem), sprType(sprT), delta(0),
deltaSet(sizeof(delta) * 8, (unsigned char*)&delta),
animState() {}
void CarSprite::setDamage(uint8_t k) {
deltaSet.set_item(k, true);
}
bool CarSprite::assertDeltaById(uint8_t k) {
GraphicsBase & style = StyleHolder::Instance().get();
PHYSFS_uint16 absNum = style.spriteNumbers.reIndex(sprNum, sprType);
GraphicsBase::SpriteInfo * info = style.getSprite(absNum);
if (k >= info->deltaCount)
return false;
return true;
}
void CarSprite::openDoor(uint8_t k) {
DoorDeltaAnimation dda(k, true);
doorAnims.push_back(dda);
}
void CarSprite::closeDoor(uint8_t k) {
doorAnims.push_back(DoorDeltaAnimation(k, false));
}
void CarSprite::setSirenAnim(bool on) {
if (!(assertDeltaById(15) && assertDeltaById(16))) {
ERROR << "Trying to set siren anim on car-sprite that has no such delta!" << std::endl;
return;
}
animState.set_item(10, on);
}
void CarSprite::update(Uint32 ticks) {
// siren anim indices
#define DSI_1 15
#define DSI_2 16
#define D_A_THEN_B(d, a, b) (d.get_item(a)) { d.set_item(a, false); d.set_item(b, true); }
// drive-anim
if (animState.get_item(0)) {}
/*
if (ticks - lt_door > 500) {
// 1-4 door-opening
if (animState.get_item(1)) {
deltaSet.set_item(6, true);
}
// 5-8 door-closing
lt_door = ticks;
}*/
DoorAnimList::iterator i = doorAnims.begin();
while (i != doorAnims.end()) {
i->update(ticks);
if (i->opening) {
if (i->doorId == 0) {
for (int k=6; k < 10; k++)
deltaSet.set_item(k, false);
deltaSet.set_item(i->getCurrentFrameNumber() + 6, true);
}
else if (i->doorId == 1) {
for (int k=11; k < 15; k++)
deltaSet.set_item(k, false);
deltaSet.set_item(i->getCurrentFrameNumber() + 11, true);
}
else if (i->doorId == 2) {
for (int k=20; k < 24; k++)
deltaSet.set_item(k, false);
deltaSet.set_item(i->getCurrentFrameNumber() + 20, true);
}
else if (i->doorId == 3) {
for (int k=24; k < 28; k++)
deltaSet.set_item(k, false);
deltaSet.set_item(i->getCurrentFrameNumber() + 24, true);
}
}
else {
if (i->doorId == 0) {
for (int k=6; k < 10; k++)
deltaSet.set_item(k, false);
if (i->getCurrentFrameNumber() > 0)
deltaSet.set_item(i->getCurrentFrameNumber() + 5, true);
}
else if (i->doorId == 1) {
for (int k=11; k < 15; k++)
deltaSet.set_item(k, false);
if (i->getCurrentFrameNumber() > 0)
deltaSet.set_item(i->getCurrentFrameNumber() + 10, true);
}
else if (i->doorId == 2) {
for (int k=20; k < 24; k++)
deltaSet.set_item(k, false);
if (i->getCurrentFrameNumber() > 0)
deltaSet.set_item(i->getCurrentFrameNumber() + 19, true);
}
else if (i->doorId == 3) {
for (int k=24; k < 28; k++)
deltaSet.set_item(k, false);
if (i->getCurrentFrameNumber() > 0)
deltaSet.set_item(i->getCurrentFrameNumber() + 23, true);
}
}
if (i->get() == Util::Animation::STOPPED) {
DoorAnimList::iterator j = i;
i++;
animState.set_item(j->doorId + 1, j->opening);
doorAnims.erase(j);
}
else
i++;
}
if (animState.get_item(10)) {
if (ticks - lt_siren > 500) {
if D_A_THEN_B(deltaSet, DSI_1, DSI_2)
else if D_A_THEN_B(deltaSet, DSI_2, DSI_1)
else { deltaSet.set_item(DSI_1, true); deltaSet.set_item(DSI_2, false); }
lt_siren = ticks;
}
}
}
CarSprite::DoorDeltaAnimation::DoorDeltaAnimation(uint8_t dId, bool dOpen) :
Util::Animation(4 + (dOpen ? 0 : 1), 5), doorId(dId), opening(dOpen) {
if (!opening) {
set(Util::Animation::PLAY_BACKWARD, Util::Animation::STOP);
jumpToFrame(4, Util::Animation::PLAY_BACKWARD);
}
else {
set(Util::Animation::PLAY_FORWARD, Util::Animation::STOP);
}
}
Car::Car(Vector3D & _pos, float _rot, uint32_t id, uint8_t _type, int16_t _remap) :
GameObject_common(_pos, _rot),
CarSprite(0, -1, GraphicsBase::SpriteNumbers::CAR), OBox(),
carInfo(*StyleHolder::Instance().get().findCarByModel(_type)) {
type = _type;
carId = id; carId = id;
type = op.type;
sprNum = carInfo.sprNum; sprNum = carInfo.sprNum;
if ((_remap > -1) && (StyleHolder::Instance().get().getFormat() == 0))
remap = carInfo.remap8[_remap];
fixSpriteType();
m_Extent = Vector3D(INT2F_DIV128(carInfo.width), m_Extent = Vector3D(INT2F_DIV128(carInfo.width),
INT2F_DIV128(carInfo.depth), INT2F_DIV128(carInfo.depth),
INT2F_DIV128(carInfo.height)); INT2F_DIV128(carInfo.height));
m_M = TranslateMatrix3D(pos); m_M = TranslateMatrix3D(pos);
m_M.RotZ(rot); m_M.RotZ(-rot);
hitPoints = carInfo.damagable;
}
void Car::fixSpriteType() {
if (carInfo.vtype == 3)
sprType = GraphicsBase::SpriteNumbers::BIKE;
else if (carInfo.vtype == 0)
sprType = GraphicsBase::SpriteNumbers::BUS;
else if (carInfo.vtype == 8)
sprType = GraphicsBase::SpriteNumbers::TRAIN;
}
Car::Car(OpenGTA::Map::ObjectPosition& op, uint32_t id) :
GameObject_common(Vector3D(INT2FLOAT_WRLD(op.x), 6.05f-INT2FLOAT_WRLD(op.z), INT2FLOAT_WRLD(op.y))),
CarSprite(0, -1, GraphicsBase::SpriteNumbers::CAR), OBox(),
carInfo(*StyleHolder::Instance().get().findCarByModel(op.type)){
carId = id;
type = op.type;
if (op.remap - 128 > 0) {
if (StyleHolder::Instance().get().getFormat() == 0)
remap = carInfo.remap8[op.remap-129];
else
WARN << "remap " << int(op.remap-129) <<
" requested but not implemented for G24" << std::endl;
}
sprNum = carInfo.sprNum;
fixSpriteType();
m_Extent = Vector3D(INT2F_DIV128(carInfo.width),
INT2F_DIV128(carInfo.depth) ,
INT2F_DIV128(carInfo.height));
m_M = TranslateMatrix3D(pos);
rot = op.rotation * 360 / 1024; rot = op.rotation * 360 / 1024;
m_M.RotZ(-rot);
hitPoints = carInfo.damagable;
} }
Car::Car(const Car & other) : Car::Car(const Car & other) :
GameObject_common(other), Sprite(other), OBox(other), GameObject_common(other), CarSprite(other), OBox(other),
carInfo(*StyleHolder::Instance().get().findCarByModel(other.type)) { carInfo(*StyleHolder::Instance().get().findCarByModel(other.type)) {
type = other.type; type = other.type;
m_M = TranslateMatrix3D(pos); m_M = TranslateMatrix3D(pos);
m_M.RotZ(rot); m_M.RotZ(-rot);
hitPoints = other.hitPoints;
carId = other.carId; carId = other.carId;
} }
void Car::update(Uint32 ticks) { void Car::update(Uint32 ticks) {
//m_M = TranslateMatrix3D(pos);
//m_M.RotZ(rot+90);
CarSprite::update(ticks);
}
void Car::damageAt(const Vector3D & hit, uint32_t dmg) {
float angle = Util::xz_angle(Vector3D(0, 0, 0), hit);
INFO << "hit angle: " << angle << std::endl;
/*
* front rear
* 270
* 0 _|o---o| _ 180
* |o---o|
* 45 90
*/
#define A1 60
#define A2 (180 - A1)
#define A3 (180 + A1)
#define A4 (360 - A1)
uint8_t k = 0;
if (angle <= A1) {
// front left
k = 3;
}
else if (angle <= A2) {
// left side
k = 2;
}
else if (angle < 180.0f) {
// rear left
k = 1;
}
else if (angle <= A3) {
// rear right
k = 4;
}
else if (angle <= A4) {
// right side
k = 5;
}
else {
// right front
k = 0;
}
setDamage(k);
hitPoints -= dmg;
if (hitPoints <= 0)
explode();
}
void Car::explode() {
//SpriteManagerHolder::Instance().removeCar(carId);
//return;
Vector3D exp_pos(pos);
exp_pos.y += 0.1f;
SpriteManagerHolder::Instance().createExplosion(exp_pos);
sprNum = 0;
remap = -1;
sprType = GraphicsBase::SpriteNumbers::WCAR;
delta = 0;
} }
SpriteObject::SpriteObject(OpenGTA::Map::ObjectPosition& op, uint32_t id) : SpriteObject::SpriteObject(OpenGTA::Map::ObjectPosition& op, uint32_t id) :
@ -487,7 +764,7 @@ namespace OpenGTA {
INT2F_DIV128(style.objectInfos[op.type]->depth), INT2F_DIV128(style.objectInfos[op.type]->depth),
INT2F_DIV128(style.objectInfos[op.type]->height)); INT2F_DIV128(style.objectInfos[op.type]->height));
m_M = TranslateMatrix3D(pos); m_M = TranslateMatrix3D(pos);
m_M.RotZ(rot); m_M.RotZ(-rot);
rot = op.rotation * 360 / 1024; rot = op.rotation * 360 / 1024;
isActive = true; isActive = true;
} }
@ -496,7 +773,7 @@ namespace OpenGTA {
GameObject_common(pos), Sprite(sprNum, -1, sprT), OBox() { GameObject_common(pos), Sprite(sprNum, -1, sprT), OBox() {
isActive = true; isActive = true;
m_M = TranslateMatrix3D(pos); m_M = TranslateMatrix3D(pos);
m_M.RotZ(rot); m_M.RotZ(-rot);
} }
SpriteObject::SpriteObject(const SpriteObject & other) : SpriteObject::SpriteObject(const SpriteObject & other) :
@ -504,7 +781,7 @@ namespace OpenGTA {
objId(other.objId) { objId(other.objId) {
m_M = TranslateMatrix3D(pos); m_M = TranslateMatrix3D(pos);
m_M.RotZ(rot); m_M.RotZ(-rot);
isActive = other.isActive; isActive = other.isActive;
} }
@ -525,6 +802,86 @@ namespace OpenGTA {
typeId(other.typeId), delta(other.delta), endsAtTick(other.endsAtTick), typeId(other.typeId), delta(other.delta), endsAtTick(other.endsAtTick),
owner(other.owner), lastUpdateAt(other.lastUpdateAt) {} owner(other.owner), lastUpdateAt(other.lastUpdateAt) {}
bool Projectile::testCollideBlock_flat(Util::CellIterator & ci, Vector3D & newp) {
Map::BlockInfo & bi = ci.getBlock();
if (bi.top) {
Math::Plane plane(Vector3D(ci.x, ci.z, ci.y), Vector3D(0, 0, -1));
Vector3D hit_pos;
if (plane.segmentIntersect(pos, newp, hit_pos)) {
INFO << "intersect flat-t: " << hit_pos.x << " " << hit_pos.y << " " <<hit_pos.z << std::endl;
if (hit_pos.x >= ci.x && hit_pos.x <= ci.x + 1) {
newp = hit_pos;
return true;
}
}
}
if (bi.left) {
Math::Plane plane(Vector3D(ci.x, ci.z, ci.y), Vector3D(-1, 0, 0));
Vector3D hit_pos;
if (plane.segmentIntersect(pos, newp, hit_pos)) {
INFO << "intersect flat-l: " << hit_pos.x << " " << hit_pos.y << " " <<hit_pos.z << std::endl;
if (hit_pos.z >= ci.y && hit_pos.z <= ci.y + 1) {
newp = hit_pos;
return true;
}
}
}
return false;
}
bool Projectile::testCollideBlock(Util::CellIterator & ci, Vector3D & newp) {
Map::BlockInfo & bi = ci.getBlock();
//INFO << "pos: " << ci.x << " " << ci.y << " " << ci.z << std::endl;
//if (bi.isFlat())
// return false;
if (bi.left) {
Math::Plane plane(Vector3D(ci.x, ci.z, ci.y), Vector3D(-1, 0, 0));
Vector3D hit_pos;
if (plane.segmentIntersect(pos, newp, hit_pos)) {
INFO << "intersect left: " << hit_pos.x << " " << hit_pos.y << " " <<hit_pos.z << std::endl;
if (hit_pos.z >= ci.y && hit_pos.z <= ci.y + 1) {
newp = hit_pos;
return true;
}
}
}
if (bi.right && !bi.isFlat()) {
Math::Plane plane(Vector3D(ci.x+1, ci.z, ci.y), Vector3D(1, 0, 0));
Vector3D hit_pos;
if (plane.segmentIntersect(pos, newp, hit_pos)) {
INFO << "intersect right: " << hit_pos.x << " " << hit_pos.y << " " <<hit_pos.z << std::endl;
if (hit_pos.z >= ci.y && hit_pos.z <= ci.y + 1) {
newp = hit_pos;
return true;
}
}
}
if (bi.top) {
Math::Plane plane(Vector3D(ci.x, ci.z, ci.y), Vector3D(0, 0, -1));
Vector3D hit_pos;
if (plane.segmentIntersect(pos, newp, hit_pos)) {
INFO << "intersect top: " << hit_pos.x << " " << hit_pos.y << " " <<hit_pos.z << std::endl;
if (hit_pos.x >= ci.x && hit_pos.x <= ci.x + 1) {
newp = hit_pos;
return true;
}
}
}
if (bi.bottom && !bi.isFlat()) {
Math::Plane plane(Vector3D(ci.x, ci.z, ci.y+1), Vector3D(0, 0, 1));
Vector3D hit_pos;
if (plane.segmentIntersect(pos, newp, hit_pos)) {
INFO << "intersect bottom: " << hit_pos.x << " " << hit_pos.y << " " <<hit_pos.z << std::endl;
if (hit_pos.x >= ci.x && hit_pos.x <= ci.x + 1) {
newp = hit_pos;
return true;
}
}
}
return false;
}
void Projectile::update(uint32_t ticks) { void Projectile::update(uint32_t ticks) {
Uint32 dt = ticks - lastUpdateAt; Uint32 dt = ticks - lastUpdateAt;
Vector3D new_pos(pos + delta * dt); Vector3D new_pos(pos + delta * dt);
@ -538,49 +895,77 @@ namespace OpenGTA {
continue; continue;
if (ped.isDead) if (ped.isDead)
continue; continue;
/*INFO << "ped " << ped.id() << " pos: " << ped.pos.x << " " << ped.pos.y << " " << ped.pos.z << std::endl;
Vector3D p = ped.GetCenterPoint(); if (ped.isLineInBox( pos, new_pos ) ) {
INFO << "CP " << p.x << " " << p.y << " " << p.z << std::endl; Vector3D p;
p = ped.m_Extent; ped.lineCrossBox(pos, new_pos, p);
INFO << "extent " << p.x << " " << p.y << " " << p.z << std::endl; float angle = Util::xz_angle(Vector3D(0,0,0), p);
for (int i=0; i < 4; i++) { INFO << angle << std::endl;
for (int j=0; j < 4; j++) { if (angle <= 90.0f || angle > 270.0f)
std::cout << "M " << ped.m_M.m[i][j] << " "; INFO << "FRONT" << std::endl;
else
INFO << "BACK" << std::endl;
ped.getShot(owner, Projectile::damageByType(typeId), true);
PlayerController & pc = LocalPlayer::Instance();
if (owner == pc.getId()) {
pc.addCash(10);
pc.addWanted(1);
} }
std::cout << std::endl;
}*/
if (ped.IsLineInBox( pos, new_pos ) ) {
INFO << "HIT ped " << ped.id() << std::endl;
ped.getShot(true);
//ped.sprType = GraphicsBase::SpriteNumbers::OBJECT;
//ped.remap = -1;
//SpriteManagerHolder::Instance().removePed(ped.pedId);
endsAtTick = 0; endsAtTick = 0;
} }
} }
std::list<Car> & clist = SpriteManagerHolder::Instance().getList<Car>();
for (std::list<Car>::iterator i = clist.begin(); i != clist.end(); i++) {
Car & car = *i;
if (car.isLineInBox(pos, new_pos)) {
INFO << "CAR HIT" << std::endl;
Vector3D p;
car.lineCrossBox(pos, new_pos, p);
car.damageAt(p, 5);
//INFO << Util::xz_angle(Vector3D(0,0,0), p) << std::endl;
delta = Vector3D(0, 0, 0);
p = Transform(p, car.m_M);
new_pos.x = p.x;
new_pos.z = p.z;
new_pos.y += 0.1f;
}
}
/*
Util::CellIterator oi(pos); Util::CellIterator oi(pos);
int collided = 0;
Util::CellIterator ni(new_pos); if (oi.isValid()) {
//FIXME ni valid? Map::BlockInfo & bi = oi.getBlock();
if (bi.isFlat()) {
if (oi.isValid() && ni.isValid()) { collided += testCollideBlock_flat(oi, new_pos);
if (oi == ni) { // only one cell to check
Math::line_intersect(pos, new_pos);//, oi.getBlock());
} }
else { // crosses cell boundary Util::CellIterator ni(oi.right());
Math::line_intersect(pos, new_pos);//, oi.getBlock()); if (ni.isValid())
//Math::line_intersect(pos, new_pos);//, ni.getBlock()); collided += testCollideBlock(ni, new_pos);
ni = oi.left();
if (ni.isValid())
collided += testCollideBlock(ni, new_pos);
ni = oi.top();
if (ni.isValid())
collided += testCollideBlock(ni, new_pos);
ni = oi.bottom();
if (ni.isValid())
collided += testCollideBlock(ni, new_pos);
} }
} if (collided)
else delta = Vector3D(0, 0, 0);
INFO << "NEITHER VALID!"<< oi.x << " " << oi.y << " " << oi.z <<std::endl;
*/
pos = new_pos; pos = new_pos;
lastUpdateAt = ticks; lastUpdateAt = ticks;
} }
uint32_t Projectile::damageByType(const uint8_t & k) {
uint32_t v = 7;
switch(k) {
case 2:
v = 150;
break;
}
return v;
}
} }

View File

@ -30,6 +30,7 @@
#include "cell_iterator.h" #include "cell_iterator.h"
#include "entity_controller.h" #include "entity_controller.h"
#include "OpenSteer/Proximity.h" #include "OpenSteer/Proximity.h"
#include "util/set.h"
namespace OpenGTA { namespace OpenGTA {
@ -90,20 +91,70 @@ namespace OpenGTA {
bool inGroundContact; bool inGroundContact;
void tryMove(Vector3D nPos); void tryMove(Vector3D nPos);
uint8_t isDead; uint8_t isDead;
void getShot(bool front = true); void getShot(uint32_t shooterId, uint32_t dmg, bool front = true);
void die(); void die();
typedef std::map<uint8_t, uint32_t> InventoryMap;
InventoryMap inventory;
uint8_t activeWeapon;
uint32_t * activeAmmo;
uint32_t aiMode;
static uint32_t fistAmmo;
struct AiData {
AiData() : id1(0), id2(0), pos1() {}
AiData(const AiData & o) : id1(o.id1), id2(o.id2), pos1(o.pos1) {}
uint32_t id1;
uint32_t id2;
Vector3D pos1;
};
AiData aiData;
Vector3D moveDelta;
}; };
class Car : public GameObject_common, public Sprite, public OBox { class CarSprite {
public:
class DoorDeltaAnimation : public Util::Animation {
public:
DoorDeltaAnimation(uint8_t dId, bool dOpen);
uint8_t doorId;
bool opening;
};
CarSprite();
CarSprite(Uint16 sprN, Sint16 rem, GraphicsBase::SpriteNumbers::SpriteTypes sprT);
CarSprite(const CarSprite & o);
Uint16 sprNum;
Sint16 remap;
GraphicsBase::SpriteNumbers::SpriteTypes sprType;
uint32_t delta;
Util::Set deltaSet;
Util::Set animState;
void setDamage(uint8_t k);
void openDoor(uint8_t k);
void closeDoor(uint8_t k);
void setSirenAnim(bool on);
bool assertDeltaById(uint8_t k);
void update(Uint32 ticks);
private:
typedef std::list<DoorDeltaAnimation> DoorAnimList;
DoorAnimList doorAnims;
Uint32 lt_siren;
};
class Car : public GameObject_common, public CarSprite, public OBox {
public: public:
Car(const Car & o); Car(const Car & o);
Car(OpenGTA::Map::ObjectPosition&, uint32_t id); Car(OpenGTA::Map::ObjectPosition&, uint32_t id);
Car(Vector3D & _pos, float _rot, uint32_t id, uint8_t _type, int16_t _remap = -1);
uint32_t carId; uint32_t carId;
inline uint32_t id() const { return carId; } inline uint32_t id() const { return carId; }
GraphicsBase::CarInfo & carInfo; GraphicsBase::CarInfo & carInfo;
uint8_t type; uint8_t type;
void update(Uint32 ticks); void update(Uint32 ticks);
Uint32 lastUpdateAt; Uint32 lastUpdateAt;
void damageAt(const Vector3D & hit, uint32_t dmg);
void explode();
private:
void fixSpriteType();
int32_t hitPoints;
}; };
class SpriteObject : public GameObject_common, public Sprite, public OBox { class SpriteObject : public GameObject_common, public Sprite, public OBox {
@ -139,6 +190,9 @@ namespace OpenGTA {
uint32_t owner; uint32_t owner;
void update(Uint32 ticks); void update(Uint32 ticks);
Uint32 lastUpdateAt; Uint32 lastUpdateAt;
bool testCollideBlock(Util::CellIterator &, Vector3D & newp);
bool testCollideBlock_flat(Util::CellIterator &, Vector3D & newp);
static uint32_t damageByType(const uint8_t & k);
}; };
} }

View File

@ -78,12 +78,12 @@ namespace OpenGL {
OpenGTA::Map::BlockInfo * block = map.getBlockAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z), PHYSFS_uint8(y)); OpenGTA::Map::BlockInfo * block = map.getBlockAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z), PHYSFS_uint8(y));
if (block->blockType() > 0 && block->blockType() <= 5) { if (block->blockType() > 0 && block->blockType() <= 5) {
float bz = slope_height_offset(block->slopeType(), eye.x - x, eye.z - z); float bz = slope_height_offset(block->slopeType(), eye.x - x, eye.z - z);
if (block->slopeType() == 0 && block->blockType() != 5) if (block->slopeType() == 0 && (block->blockType() != 5 && block->blockType() != 6))
bz -= 1; bz -= 1;
//INFO << int(block->blockType()) << ", " << eye.y << ", " << //INFO << int(block->blockType()) << ", " << eye.y << ", " <<
// eye.y - y << ", " << eye.y - y - bz << ", " << bz << std::endl; // eye.y - y << ", " << eye.y - y - bz << ", " << bz << std::endl;
float react_delta = 0.3f; float react_delta = 0.3f;
if (block->blockType() == 5) if (block->blockType() == 5 || block->blockType() == 6)
react_delta = 0.0f; react_delta = 0.0f;
if (eye.y - y - bz < react_delta) { if (eye.y - y - bz < react_delta) {
//do_grav = 0; //do_grav = 0;
@ -109,7 +109,7 @@ namespace OpenGL {
y -= 1; y -= 1;
if (y < map.getNumBlocksAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z)) && y > 0.0f) { if (y < map.getNumBlocksAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z)) && y > 0.0f) {
OpenGTA::Map::BlockInfo * block = map.getBlockAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z), PHYSFS_uint8(y)); OpenGTA::Map::BlockInfo * block = map.getBlockAtNew(PHYSFS_uint8(x), PHYSFS_uint8(z), PHYSFS_uint8(y));
if (block->blockType() == 5) { if (block->blockType() == 5 || block->blockType() == 6) {
float bz = slope_height_offset(block->slopeType(), eye.x - x, eye.z - z); float bz = slope_height_offset(block->slopeType(), eye.x - x, eye.z - z);
//INFO << eye.y << ", " << y << " bz " << bz << std::endl; //INFO << eye.y << ", " << y << " bz " << bz << std::endl;
if (eye.y - y - bz < 0.4f) { if (eye.y - y - bz < 0.4f) {

View File

@ -35,6 +35,8 @@
#include "blockdata.h" #include "blockdata.h"
#include "image_loader.h" #include "image_loader.h"
#include "blockanim.h" #include "blockanim.h"
#include "id_sys.h"
#include "map_helper.h"
float slope_height_offset(unsigned char slope_type, float dx, float dz); float slope_height_offset(unsigned char slope_type, float dx, float dz);
namespace OpenGTA { namespace OpenGTA {
@ -72,6 +74,33 @@ namespace OpenGTA {
return tex; return tex;
} }
*/ */
struct GLColor {
GLfloat rgb[3];
GLColor() { rgb[0] = rgb[1] = rgb[2] = 0; }
GLColor(GLfloat i) { rgb[0] = rgb[1] = rgb[2] = i; }
GLColor(GLfloat r, GLfloat g, GLfloat b) { rgb[0] = r; rgb[1] = g; rgb[2] = b; }
};
GLColor block_colors[8] = {
GLColor(1), // air
GLColor(0, 0, 1), // water
GLColor(0, 1, 1), // road
GLColor(1, 0, 0), // pavement
GLColor(0, 1, 0), // field
GLColor(1, 1, 0), // building
GLColor(1), // unused
GLColor(1) // unused
};
GLfloat* map_block_type_color(uint8_t k) {
// k = 6 now used to fix pavement cols
if (k == 7)
WARN << "block-type: " << int(k) << " should be unused!" << std::endl;
if (k < 8)
return block_colors[k].rgb;
ERROR << "Invalid block-type: " << int(k) << std::endl;
return block_colors[0].rgb;
}
CityView::CityView() { CityView::CityView() {
setNull(); setNull();
@ -95,6 +124,7 @@ namespace OpenGTA {
topDownView = true; topDownView = true;
drawTextured = true; drawTextured = true;
drawLines = false; drawLines = false;
drawLinesBlockType = true;
setPosition(0.0f, 0.0f, 20.0f); setPosition(0.0f, 0.0f, 20.0f);
scene_display_list = 0; scene_display_list = 0;
@ -119,8 +149,10 @@ namespace OpenGTA {
} }
bool CityView::getDrawTextured() { return drawTextured; } bool CityView::getDrawTextured() { return drawTextured; }
bool CityView::getDrawLines() { return drawLines; } bool CityView::getDrawLines() { return drawLines; }
bool CityView::getDrawLinesBlockColor() { return drawLinesBlockType; }
void CityView::setDrawTextured(bool v) { drawTextured = v; } void CityView::setDrawTextured(bool v) { drawTextured = v; }
void CityView::setDrawLines(bool v) { drawLines= v; } void CityView::setDrawLines(bool v) { drawLines= v; }
void CityView::setDrawLinesBlockColor(bool v) { drawLinesBlockType= v; }
void CityView::cleanup() { void CityView::cleanup() {
//if (loadedMap) //if (loadedMap)
// delete loadedMap; // delete loadedMap;
@ -146,6 +178,7 @@ namespace OpenGTA {
loadedMap = &MapHolder::Instance().get(); loadedMap = &MapHolder::Instance().get();
StyleHolder::Instance().load(style_f); StyleHolder::Instance().load(style_f);
style = &StyleHolder::Instance().get(); style = &StyleHolder::Instance().get();
style->setDeltaHandling(true);
/* /*
for (size_t i = 0; i < style->carInfos.size(); ++i) { for (size_t i = 0; i < style->carInfos.size(); ++i) {
OpenGTA::GraphicsBase::CarInfo * cinfo = style->carInfos[i]; OpenGTA::GraphicsBase::CarInfo * cinfo = style->carInfos[i];
@ -166,23 +199,33 @@ namespace OpenGTA {
scene_display_list = glGenLists(1); scene_display_list = glGenLists(1);
SpriteManagerHolder::Instance().clear(); SpriteManagerHolder::Instance().clear();
// safeguard against double car entries (in nyc.cmp)
Util::MapOfPair2Int d_car_map;
for (PHYSFS_uint16 oc = 0; oc < loadedMap->numObjects; oc++) { for (PHYSFS_uint16 oc = 0; oc < loadedMap->numObjects; oc++) {
OpenGTA::Map::ObjectPosition & op = loadedMap->objects[oc];
if (op.remap >= 128) {
if (Util::item_count(d_car_map, op.x, op.y) == 0)
Util::register_item1(d_car_map, op.x, op.y);
else
continue;
}
createLevelObject(&loadedMap->objects[oc]); createLevelObject(&loadedMap->objects[oc]);
} }
//SpriteManagerHolder::Instance().trainSystem.loadStations(*loadedMap); //SpriteManagerHolder::Instance().trainSystem.loadStations(*loadedMap);
activeRect.x = activeRect.y = 0;
activeRect.w = activeRect.h = 0;
} }
void CityView::createLevelObject(OpenGTA::Map::ObjectPosition *obj) { void CityView::createLevelObject(OpenGTA::Map::ObjectPosition *obj) {
SpriteManager & s_man = SpriteManagerHolder::Instance(); SpriteManager & s_man = SpriteManagerHolder::Instance();
uint32_t id = TypeIdBlackBox::requestId();
if (obj->remap >= 128) { if (obj->remap >= 128) {
Car car(*obj, 0); Car car(*obj, id);
s_man.add(car); s_man.add(car);
//s_man.addCar(car);
} }
else { else {
//GameObject gobj(*obj); SpriteObject gobj(*obj, id);
SpriteObject gobj(*obj, 0);
s_man.add(gobj); s_man.add(gobj);
//s_man.addObject(gobj);
} }
} }
void CityView::setZoom(const GLfloat zoom) { void CityView::setZoom(const GLfloat zoom) {
@ -232,6 +275,7 @@ namespace OpenGTA {
int yi = int(z); int yi = int(z);
//int zi = int(z); //int zi = int(z);
float h = 0.5f; float h = 0.5f;
WARN << "THIS FUNCTION SHOULD NOT BE USED!" << std::endl;
PHYSFS_uint16 emptycount = loadedMap->getNumBlocksAt(xi, yi); PHYSFS_uint16 emptycount = loadedMap->getNumBlocksAt(xi, yi);
for (int c=6-emptycount; c >= 1; c--) { for (int c=6-emptycount; c >= 1; c--) {
OpenGTA::Map::BlockInfo* bi = loadedMap->getBlockAt(xi, yi, c); OpenGTA::Map::BlockInfo* bi = loadedMap->getBlockAt(xi, yi, c);
@ -250,14 +294,56 @@ namespace OpenGTA {
} }
OpenGL::PagedTexture CityView::renderMap2Texture() { OpenGL::PagedTexture CityView::renderMap2Texture() {
uint32_t width = OpenGL::ScreenHolder::Instance().getWidth(); OpenGL::Screen & screen = OpenGL::ScreenHolder::Instance();
uint32_t height = OpenGL::ScreenHolder::Instance().getHeight(); uint32_t width = screen.getWidth();
uint32_t height = screen.getHeight();
uint32_t gl_h = 1;
while (gl_h < height)
gl_h <<= 1;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFinish();
Vector3D v_off(0,0,0);
int persp_find_done = 0;
int break_loop_safe = 500;
while (persp_find_done != 3) {
OpenGL::ScreenHolder::Instance().set3DProjection(); OpenGL::ScreenHolder::Instance().set3DProjection();
glRotatef(180, 0, 0, 1); glRotatef(180, 0, 0, 1);
gluLookAt(128, 230, 128, 128, 0, 128, 0.0f, 0.0f, 1.0f);
glTranslatef(-42, 0, 0); gluLookAt(128+v_off.x, 230, 128+v_off.y, 128+v_off.x, 0, 128+v_off.y, 0.0f, 0.0f, 1.0f);
GLint viewport[4];
GLdouble mvmatrix[16], projmatrix[16];
GLdouble winx, winy, winz;
glGetIntegerv (GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
gluProject(0, 0, 0, mvmatrix, projmatrix, viewport, &winx, &winy, &winz);
if (winx > 0.5f)
v_off.x += 0.2f;
else if (winx < -0.5f)
v_off.x -= 0.2f;
else
persp_find_done |= 1;
INFO << winx << " " << winy << std::endl;
gluProject(256, 0, 256, mvmatrix, projmatrix, viewport, &winx, &winy, &winz);
if (winy < -0.5f)
v_off.y += 0.2f;
else if (winy > 0.5f)
v_off.y -= 0.2f;
else
persp_find_done |= 2;
break_loop_safe--;
if (break_loop_safe == 0) {
WARN << "breaking out of loop - NOT GOOD!" << std::endl;
persp_find_done = 3;
}
INFO << winx << " " << winy << std::endl;
}
//glTranslatef(-35, 0, 0);
for (int i = 0; i <= 255; i++) { for (int i = 0; i <= 255; i++) {
for (int j= 0; j <= 255; j++) { for (int j= 0; j <= 255; j++) {
glPushMatrix(); glPushMatrix();
@ -274,16 +360,27 @@ namespace OpenGTA {
} }
GL_CHECKERROR; GL_CHECKERROR;
uint32_t gl_h = 1; glFinish();
while (gl_h < height) /*
gl_h <<= 1; GLuint txtnumber;
glGenTextures(1, &txtnumber); // Create 1 Texture
glBindTexture(GL_TEXTURE_2D, txtnumber); // Bind The Texture
GL_CHECKERROR;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, gl_h, gl_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
GL_CHECKERROR;
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width/2, height/2);
GL_CHECKERROR;
//glViewport(0, 0, width, height);
return OpenGL::PagedTexture(txtnumber, 0, 0, 1, 1);
*/
uint32_t img_size = gl_h * gl_h * 3; uint32_t img_size = gl_h * gl_h * 3;
uint8_t *img_buf = Util::BufferCacheHolder::Instance().requestBuffer(img_size); uint8_t *img_buf = Util::BufferCacheHolder::Instance().requestBuffer(img_size);
glReadBuffer(GL_BACK); glReadBuffer(GL_BACK);
for (uint32_t i = 0; i < gl_h; i++) { //for (uint32_t i = 0; i < gl_h; i++) {
glReadPixels(0, i, gl_h, 1, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)(img_buf + gl_h * 3 * i)); // glReadPixels(0, i, gl_h, 1, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)(img_buf + gl_h * 3 * i));
} //}
glReadPixels(0, 0, gl_h, gl_h, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)img_buf);
GL_CHECKERROR; GL_CHECKERROR;
sideCache->sink(); sideCache->sink();
@ -295,12 +392,26 @@ namespace OpenGTA {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
uint32_t y_off = 100;
uint32_t x = 0;
while (*(img_buf + y_off * gl_h * 3 + x) == 0 && *(img_buf + y_off * gl_h * 3 + x+1) == 0 &&
*(img_buf + y_off * gl_h * 3 + x + 2) == 0)
x += 3;
INFO << "color after x = " << x/3 << std::endl;
x = gl_h-3;
while (*(img_buf + y_off * gl_h * 3 + x) == 0 && *(img_buf + y_off * gl_h * 3 + x+1) == 0 &&
*(img_buf + y_off * gl_h * 3 + x+2) == 0)
x -= 3;
INFO << "color after x = " << x/3 << std::endl;
GLuint tex = ImageUtil::createGLTexture(gl_h, gl_h, false, img_buf); GLuint tex = ImageUtil::createGLTexture(gl_h, gl_h, false, img_buf);
float f_h = float(height) / gl_h; float f_h = float(height) / gl_h;
float f_w = float(width) / gl_h; float f_w = float(width) / gl_h;
//float horiz_corr = (1.0f - f_w) / 2.0f; //float horiz_corr = (1.0f - f_w) / 2.0f;
//return OpenGL::PagedTexture(tex, 0+horiz_corr, 0, f_w+horiz_corr, f_h); //return OpenGL::PagedTexture(tex, 0+horiz_corr, 0, f_w+horiz_corr, f_h);
return OpenGL::PagedTexture(tex, 0, 0, f_w, f_h);
return OpenGL::PagedTexture(tex, 0, 0, f_h, f_h);
} }
void CityView::draw(Uint32 ticks) { void CityView::draw(Uint32 ticks) {
@ -363,6 +474,8 @@ namespace OpenGTA {
if (y2 > 255) if (y2 > 255)
y2 = 255; y2 = 255;
//INFO << activeRect.x << ", " << activeRect.y << " -> " <<
// activeRect.x+activeRect.w << ", " << activeRect.y + activeRect.h << std::endl;
activeRect.x = x1; activeRect.x = x1;
activeRect.y = y1; activeRect.y = y1;
activeRect.w = x2 - x1; activeRect.w = x2 - x1;
@ -405,6 +518,12 @@ namespace OpenGTA {
for (int c=0; c < maxcount; ++c) { for (int c=0; c < maxcount; ++c) {
++scene_rendered_blocks; ++scene_rendered_blocks;
glPushMatrix(); glPushMatrix();
if (c < maxcount - 1) {
Map::BlockInfo * bi = loadedMap->getBlockAtNew(j, i, c + 1);
aboveBlockType = bi->blockType();
}
else
aboveBlockType = loadedMap->getBlockAtNew(j, i, c)->blockType();
drawBlock(loadedMap->getBlockAtNew(j, i, c)); drawBlock(loadedMap->getBlockAtNew(j, i, c));
glPopMatrix(); glPopMatrix();
glTranslatef(0.0f, 1.0f, 0.0f); glTranslatef(0.0f, 1.0f, 0.0f);
@ -712,6 +831,14 @@ namespace OpenGTA {
} }
} }
#define RESET_COLOR glColor3f(1, 1, 1)
#define COLOR_OFF if (drawLinesBlockType) RESET_COLOR
#define COLOR_BY_BLOCK(idx) { GLfloat *_c = map_block_type_color(idx); glColor3f(_c[0], _c[1], _c[2]); }
#define COLOR_ON if (drawLinesBlockType) COLOR_BY_BLOCK(aboveBlockType)
//#define COLOR_ON if (drawLinesBlockType) COLOR_BY_BLOCK(bi->blockType())
if (drawLinesBlockType)
// handle flat/transparent case // handle flat/transparent case
if (is_flat) { if (is_flat) {
if (bi->lid) { if (bi->lid) {
@ -738,6 +865,7 @@ namespace OpenGTA {
// lines // lines
if (drawLines) { if (drawLines) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
COLOR_ON;
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (int j=0; j < 4; j++) { for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][0][j][0], glVertex3f(SLOPE_RAW_DATA[which][0][j][0],
@ -750,6 +878,7 @@ namespace OpenGTA {
glEnd(); glEnd();
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
// end-of-lines // end-of-lines
COLOR_OFF;
} }
} }
#undef MSWAP #undef MSWAP
@ -790,6 +919,7 @@ namespace OpenGTA {
// lines // lines
if (drawLines) { if (drawLines) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
COLOR_ON;
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (int j=0; j < 4; j++) { for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][2][j][0], glVertex3f(SLOPE_RAW_DATA[which][2][j][0],
@ -810,6 +940,7 @@ namespace OpenGTA {
glEnd(); glEnd();
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
// end-of-lines // end-of-lines
COLOR_OFF;
} }
} }
jj = 0; jj = 0;
@ -848,6 +979,7 @@ namespace OpenGTA {
// lines // lines
if (drawLines) { if (drawLines) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
COLOR_ON;
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (int j=0; j < 4; j++) { for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][3][j][0], glVertex3f(SLOPE_RAW_DATA[which][3][j][0],
@ -866,6 +998,7 @@ namespace OpenGTA {
SLOPE_RAW_DATA[which][4][0][1], SLOPE_RAW_DATA[which][4][0][1],
SLOPE_RAW_DATA[which][4][0][2]); SLOPE_RAW_DATA[which][4][0][2]);
glEnd(); glEnd();
COLOR_OFF;
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
// end-of-lines // end-of-lines
} }
@ -896,6 +1029,7 @@ namespace OpenGTA {
// lines // lines
if (drawLines) { if (drawLines) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
COLOR_ON;
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (int j=0; j < 4; j++) { for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][0][j][0], glVertex3f(SLOPE_RAW_DATA[which][0][j][0],
@ -908,6 +1042,7 @@ namespace OpenGTA {
glEnd(); glEnd();
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
// end-of-lines // end-of-lines
COLOR_OFF;
} }
} }
jj = 0; // only 'lid' rotated jj = 0; // only 'lid' rotated
@ -947,6 +1082,7 @@ namespace OpenGTA {
// lines // lines
if (drawLines) { if (drawLines) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
COLOR_ON;
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (int j=0; j < 4; j++) { for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][2][j][0], glVertex3f(SLOPE_RAW_DATA[which][2][j][0],
@ -959,6 +1095,7 @@ namespace OpenGTA {
glEnd(); glEnd();
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
// end-of-lines // end-of-lines
COLOR_OFF;
} }
} }
jj = 0; jj = 0;
@ -989,6 +1126,7 @@ namespace OpenGTA {
// lines // lines
if (drawLines) { if (drawLines) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
COLOR_ON;
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (int j=0; j < 4; j++) { for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][1][j][0], glVertex3f(SLOPE_RAW_DATA[which][1][j][0],
@ -1001,6 +1139,7 @@ namespace OpenGTA {
glEnd(); glEnd();
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
// end-of-lines // end-of-lines
COLOR_OFF;
} }
} }
/*memcpy(sideTex1, sideTex1_bak, 8 * sizeof(GLfloat)); /*memcpy(sideTex1, sideTex1_bak, 8 * sizeof(GLfloat));
@ -1037,6 +1176,7 @@ namespace OpenGTA {
// lines // lines
if (drawLines) { if (drawLines) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
COLOR_ON;
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (int j=0; j < 4; j++) { for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][3][j][0], glVertex3f(SLOPE_RAW_DATA[which][3][j][0],
@ -1049,6 +1189,7 @@ namespace OpenGTA {
glEnd(); glEnd();
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
// end-of-lines // end-of-lines
COLOR_OFF;
} }
} }
jj = 0; jj = 0;
@ -1079,6 +1220,7 @@ namespace OpenGTA {
// lines // lines
if (drawLines) { if (drawLines) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
COLOR_ON;
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (int j=0; j < 4; j++) { for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][4][j][0], glVertex3f(SLOPE_RAW_DATA[which][4][j][0],
@ -1091,6 +1233,7 @@ namespace OpenGTA {
glEnd(); glEnd();
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
// end-of-lines // end-of-lines
COLOR_OFF;
} }
} }

View File

@ -54,10 +54,12 @@ namespace OpenGTA {
NavData::Sector* getCurrentSector(); NavData::Sector* getCurrentSector();
OpenGL::PagedTexture renderMap2Texture(); OpenGL::PagedTexture renderMap2Texture();
bool CityView::getDrawTextured(); bool getDrawTextured();
bool CityView::getDrawLines(); bool getDrawLines();
void CityView::setDrawTextured(bool v); bool getDrawLinesBlockColor();
void CityView::setDrawLines(bool v); void setDrawTextured(bool v);
void setDrawLines(bool v);
void setDrawLinesBlockColor(bool v);
void resetTextures(); void resetTextures();
const SDL_Rect & getActiveRect() { return activeRect; } const SDL_Rect & getActiveRect() { return activeRect; }
@ -83,6 +85,9 @@ namespace OpenGTA {
bool topDownView; bool topDownView;
bool drawTextured; bool drawTextured;
bool drawLines; bool drawLines;
bool drawLinesBlockType;
bool drawHeadingMarkers;
uint8_t aboveBlockType;
SDL_Rect activeRect; SDL_Rect activeRect;
SDL_Rect drawnRect; SDL_Rect drawnRect;
@ -92,7 +97,6 @@ namespace OpenGTA {
GLuint scene_display_list; GLuint scene_display_list;
bool scene_is_dirty; bool scene_is_dirty;
bool drawHeadingMarkers;
int texFlipTest; int texFlipTest;
Uint32 lastCacheEmptyTicks; Uint32 lastCacheEmptyTicks;

View File

@ -95,6 +95,34 @@ namespace OpenGL {
return move; return move;
} }
GLfloat DrawableFont::drawString_r2l(const std::string & text) {
assert(texCache != NULL);
assert(fontSource != NULL);
std::string::const_reverse_iterator i = text.rbegin();
std::string::const_reverse_iterator e = text.rend();
GLfloat move = 0.0f;
while (i != e) {
if (*i != ' ') {
FontQuad* character = NULL;
std::map<char, FontQuad*>::const_iterator j = drawables.find(*i);
if (j == drawables.end()) {
character = createDrawableCharacter(*i);
drawables[*i] = character;
}
else {
GLfloat mm = float(fontSource->getMoveWidth(*i)) * 1.1f * scale;
glTranslatef(-mm, 0.0f, 0.0f);
character = j->second;
move += mm;
}
Renderer<FontQuad>::draw(*character);
}
i++;
}
return move;
}
uint16_t DrawableFont::getHeight() { uint16_t DrawableFont::getHeight() {
return scale * fontSource->getCharHeight(); return scale * fontSource->getCharHeight();
} }

View File

@ -36,6 +36,7 @@ namespace OpenGL {
~DrawableFont(); ~DrawableFont();
void loadFont(const std::string & filename); void loadFont(const std::string & filename);
GLfloat drawString(const std::string & text) ; GLfloat drawString(const std::string & text) ;
GLfloat drawString_r2l(const std::string & text) ;
void setScale(unsigned int newScale); void setScale(unsigned int newScale);
uint16_t getHeight(); uint16_t getHeight();
void resetTextures(); void resetTextures();

View File

@ -25,6 +25,7 @@
#include "log.h" #include "log.h"
#include "buffercache.h" #include "buffercache.h"
#include "m_exceptions.h" #include "m_exceptions.h"
#include "image_loader.h"
namespace OpenGL { namespace OpenGL {
#ifndef DEFAULT_SCREEN_WIDTH #ifndef DEFAULT_SCREEN_WIDTH
@ -32,6 +33,9 @@ namespace OpenGL {
#endif #endif
#ifndef DEFAULT_SCREEN_HEIGHT #ifndef DEFAULT_SCREEN_HEIGHT
#define DEFAULT_SCREEN_HEIGHT 480 #define DEFAULT_SCREEN_HEIGHT 480
#endif
#ifndef DEFAULT_SCREEN_VSYNC
#define DEFAULT_SCREEN_VSYNC 0
#endif #endif
Screen::Screen() { Screen::Screen() {
@ -43,6 +47,8 @@ namespace OpenGL {
fieldOfView = 60.0f; fieldOfView = 60.0f;
nearPlane = 0.1f; nearPlane = 0.1f;
farPlane = 250.0f; farPlane = 250.0f;
// 0: no vsync, 1: sdl, 2 native
useVsync = DEFAULT_SCREEN_VSYNC;
} }
void Screen::activate(Uint32 w, Uint32 h) { void Screen::activate(Uint32 w, Uint32 h) {
@ -52,6 +58,7 @@ namespace OpenGL {
height = h; height = h;
initSDL(); initSDL();
resize(width, height); resize(width, height);
INFO << "activating screen: " << width << "x" << height << std::endl;
initGL(); initGL();
setSystemMouseCursor(false); setSystemMouseCursor(false);
} }
@ -62,6 +69,10 @@ namespace OpenGL {
farPlane = far_p; farPlane = far_p;
} }
void Screen::setupVsync(size_t mode) {
useVsync = mode;
}
void Screen::setSystemMouseCursor(bool visible) { void Screen::setSystemMouseCursor(bool visible) {
SDL_ShowCursor((visible ? SDL_ENABLE : SDL_DISABLE)); SDL_ShowCursor((visible ? SDL_ENABLE : SDL_DISABLE));
} }
@ -112,7 +123,7 @@ namespace OpenGL {
const char* sdl_err = SDL_GetError(); const char* sdl_err = SDL_GetError();
if (strlen(sdl_err) > 0) if (strlen(sdl_err) > 0)
INFO << "sdl_init complained: " << sdl_err << std::endl; WARN << "SDL_Init complained: " << sdl_err << std::endl;
SDL_ClearError(); SDL_ClearError();
const SDL_VideoInfo *vInfo = SDL_GetVideoInfo(); const SDL_VideoInfo *vInfo = SDL_GetVideoInfo();
@ -166,33 +177,75 @@ namespace OpenGL {
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1);
#ifdef HAVE_SDL_VSYNC #ifdef HAVE_SDL_VSYNC
if (useVsync == 1) {
SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 1); SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 1);
INFO << "enabling vertical sync:" << " SDL" << std::endl;
}
#else
if (useVsync == 1)
WARN << "Cannot use SDL vsync - option disabled while compiling" << std::endl;
#endif #endif
sdl_err = SDL_GetError(); sdl_err = SDL_GetError();
if (strlen(sdl_err) > 0) if (strlen(sdl_err) > 0)
ERROR << "setting sdl_gl attributes: " << sdl_err << std::endl; ERROR << "setting sdl_gl attributes: " << sdl_err << std::endl;
} }
void Screen::initGL() { void Screen::initGL() {
GL_CHECKERROR; GL_CHECKERROR;
//GLfloat LightAmbient[] = { 0.8f, 0.8f, 0.8f, 1.0f }; if (useVsync == 2) {
//GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; #ifdef LINUX
//GLfloat LightPosition[] = { 128.0f, 200.0f, 128.0f, 1.0f }; int (*fp)(int) = (int(*)(int)) SDL_GL_GetProcAddress("glXSwapIntervalMESA");
if (fp) {
fp(1);
INFO << "enabling vertical sync:" << " GLX" << std::endl;
}
else
ERROR << "No symbol 'glXSwapIntervalMESA' found - cannot use GLX vsync" << std::endl;
#else
typedef void (APIENTRY * WGLSWAPINTERVALEXT) (int);
WGLSWAPINTERVALEXT wglSwapIntervalEXT =
(WGLSWAPINTERVALEXT) wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT)
{
wglSwapIntervalEXT(1); // set vertical synchronisation
INFO << "enabling vertical sync:" << " WGL" << std::endl;
}
else
ERROR << "No symbol 'wglSwapIntervalEXT' found - cannot use WGL vsync" << std::endl;
#endif
}
/*
GLfloat LightAmbient[] = { 0.1f, 0.1f, 0.1f, 1.0f };
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[] = { 1.0f, 1.0f, 0.0f, 0.0f };
*/
//glShadeModel( GL_SMOOTH ); //glShadeModel( GL_SMOOTH );
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glEnable( GL_DEPTH_TEST ); glEnable( GL_DEPTH_TEST );
//glEnable( GL_LIGHTING ); /*
glEnable( GL_LIGHTING );
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
//glLightfv( GL_LIGHT0, GL_AMBIENT, LightAmbient ); glLightfv( GL_LIGHT0, GL_AMBIENT, LightAmbient );
//glLightfv( GL_LIGHT0, GL_DIFFUSE, LightDiffuse ); glLightfv( GL_LIGHT0, GL_DIFFUSE, LightDiffuse );
//glLightfv( GL_LIGHT0, GL_POSITION, LightPosition ); glLightfv( GL_LIGHT0, GL_POSITION, LightPosition );
//glEnable( GL_LIGHT0 ); glEnable( GL_LIGHT0 );
*/
glEnable( GL_COLOR_MATERIAL); glEnable( GL_COLOR_MATERIAL);
glCullFace(GL_BACK); glCullFace(GL_BACK);
//glPolygonMode(GL_FRONT, GL_FILL); //glPolygonMode(GL_FRONT, GL_FILL);
//glPolygonMode(GL_BACK, GL_LINE); //glPolygonMode(GL_BACK, GL_LINE);
glEnable(GL_TEXTURE_2D);
if (queryExtension("GL_EXT_texture_filter_anisotropic")) {
GLfloat maxAniso = 1.0f;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
//if (maxAniso >= 2.0f)
ImageUtil::supportedMaxAnisoDegree = maxAniso;
INFO << "GL supports anisotropic filtering with degree: " << maxAniso << std::endl;
}
GL_CHECKERROR; GL_CHECKERROR;
} }
@ -256,4 +309,18 @@ namespace OpenGL {
SDL_SaveBMP(image, filename); SDL_SaveBMP(image, filename);
SDL_FreeSurface( image ); SDL_FreeSurface( image );
} }
GLboolean Screen::queryExtension(const char *extName) {
// from the 'Red Book'
char *p = (char *) glGetString(GL_EXTENSIONS);
char *end = p + strlen(p);
while (p < end) {
size_t n = strcspn(p, " ");
if ((strlen(extName)==n) && (strncmp(extName,p,n)==0)) {
return GL_TRUE;
}
p += (n + 1);
}
return GL_FALSE;
}
} }

View File

@ -48,6 +48,9 @@ namespace OpenGL {
inline float getNearPlane() { return nearPlane; } inline float getNearPlane() { return nearPlane; }
inline float getFarPlane() { return farPlane; } inline float getFarPlane() { return farPlane; }
void setupGlVars( float fov, float near_p, float far_p); void setupGlVars( float fov, float near_p, float far_p);
void setupVsync( size_t enabled );
static GLboolean queryExtension(const char *extName);
private: private:
void initGL(); void initGL();
@ -55,6 +58,7 @@ namespace OpenGL {
Uint32 width, height; Uint32 width, height;
Uint32 bpp; Uint32 bpp;
Uint32 videoFlags; Uint32 videoFlags;
size_t useVsync;
float fieldOfView; float fieldOfView;
float nearPlane; float nearPlane;
float farPlane; float farPlane;

View File

@ -24,6 +24,7 @@
#include <cassert> #include <cassert>
#include <SDL_image.h> #include <SDL_image.h>
#include "gl_spritecache.h" #include "gl_spritecache.h"
#include "image_loader.h"
#include "opengta.h" #include "opengta.h"
#include "dataholder.h" #include "dataholder.h"
#include "buffercache.h" #include "buffercache.h"
@ -188,8 +189,6 @@ namespace OpenGL {
INFO << "creating new sprite: " << sprite_num << " remap: " << remap << std::endl; INFO << "creating new sprite: " << sprite_num << " remap: " << remap << std::endl;
unsigned char* src = OpenGTA::StyleHolder::Instance().get(). unsigned char* src = OpenGTA::StyleHolder::Instance().get().
getSpriteBitmap(sprite_num, remap , delta); getSpriteBitmap(sprite_num, remap , delta);
unsigned int glwidth = 1;
unsigned int glheight = 1;
#if 0 #if 0
if (sprite_num == 257) { if (sprite_num == 257) {
info->w = 72; info->w = 72;
@ -210,6 +209,9 @@ namespace OpenGL {
} }
#endif #endif
#if 0
int glwidth = 1;
int glheight = 1;
while(glwidth < info->w) while(glwidth < info->w)
glwidth <<= 1; glwidth <<= 1;
@ -225,8 +227,21 @@ namespace OpenGL {
t += glwidth * 4; t += glwidth * 4;
r += info->w * 4; r += info->w * 4;
} }
#endif
ImageUtil::NextPowerOfTwo npot(info->w, info->h);
Util::BufferCache & bc = Util::BufferCacheHolder::Instance();
uint8_t* dst = bc.requestBuffer(npot.w * npot.h * 4);
ImageUtil::copyImage2Image(dst, src, info->w * 4, info->h, npot.w * 4);
bc.unlockBuffer(src);
#ifdef DO_SCALE2X #ifdef DO_SCALE2X
if (doScale2x) { if (doScale2x) {
bc.lockBuffer(dst);
uint8_t* dst_scalex = ImageUtil::scale2x_32bit(dst, npot.w, npot.h);
bc.unlockBuffer(dst);
dst = dst_scalex;
#if 0
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b))
@ -236,9 +251,9 @@ namespace OpenGL {
Util::BufferCacheHolder::Instance().lockBuffer(dst); Util::BufferCacheHolder::Instance().lockBuffer(dst);
Uint8* dstpix = Util::BufferCacheHolder::Instance().requestBuffer(glwidth * glheight * 4 * 4); Uint8* dstpix = Util::BufferCacheHolder::Instance().requestBuffer(glwidth * glheight * 4 * 4);
Uint32 E0, E1, E2, E3, B, D, E, F, H; Uint32 E0, E1, E2, E3, B, D, E, F, H;
for(unsigned int looph = 0; looph < glheight; ++looph) for(int looph = 0; looph < glheight; ++looph)
{ {
for(unsigned int loopw = 0; loopw < glwidth; ++ loopw) for(int loopw = 0; loopw < glwidth; ++ loopw)
{ {
B = *(Uint32*)(srcpix + (MAX(0,looph-1)*srcpitch) + (4*loopw)); B = *(Uint32*)(srcpix + (MAX(0,looph-1)*srcpitch) + (4*loopw));
D = *(Uint32*)(srcpix + (looph*srcpitch) + (4*MAX(0,loopw-1))); D = *(Uint32*)(srcpix + (looph*srcpitch) + (4*MAX(0,loopw-1)));
@ -259,10 +274,14 @@ namespace OpenGL {
} }
Util::BufferCacheHolder::Instance().unlockBuffer(dst); Util::BufferCacheHolder::Instance().unlockBuffer(dst);
dst = dstpix; dst = dstpix;
#endif
} }
#endif #endif
GLuint texid; GLuint texid = (doScale2x) ?
ImageUtil::createGLTexture(npot.w * 2, npot.h * 2, true, dst)
: ImageUtil::createGLTexture(npot.w, npot.h, true, dst);
#if 0
glGenTextures(1, &texid); glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid); glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -276,9 +295,11 @@ namespace OpenGL {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glwidth, glheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, dst); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glwidth, glheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, dst);
#else #else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glwidth, glheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, dst); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glwidth, glheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, dst);
#endif
#endif #endif
return OpenGL::PagedTexture(texid, 0, 0, return OpenGL::PagedTexture(texid, 0, 0,
float(info->w)/float(glwidth), float(info->h)/float(glheight)); float(info->w)/float(npot.w), float(info->h)/float(npot.h));
} }
} }

View File

@ -22,6 +22,7 @@
************************************************************************/ ************************************************************************/
#ifndef SPRITE_CACHE_H #ifndef SPRITE_CACHE_H
#define SPRITE_CACHE_H #define SPRITE_CACHE_H
#include <cstddef>
#include <physfs.h> #include <physfs.h>
#include "Singleton.h" #include "Singleton.h"
#include "gl_pagedtexture.h" #include "gl_pagedtexture.h"
@ -65,7 +66,7 @@ namespace OpenGL {
OpenGTA::GraphicsBase::SpriteNumbers::SpriteTypes, OpenGTA::GraphicsBase::SpriteNumbers::SpriteTypes,
PHYSFS_sint16 remap, PHYSFS_uint32 delta); PHYSFS_sint16 remap, PHYSFS_uint32 delta);
OpenGL::PagedTexture SpriteCache::createSprite(size_t sprite_num, PHYSFS_sint16 remap, OpenGL::PagedTexture createSprite(size_t sprite_num, PHYSFS_sint16 remap,
PHYSFS_uint32 delta, OpenGTA::GraphicsBase::SpriteInfo* info); PHYSFS_uint32 delta, OpenGTA::GraphicsBase::SpriteInfo* info);
private: private:

View File

@ -63,6 +63,11 @@ these remain under their respective licenses.
Copyright (C) 2000 Amir Geva Copyright (C) 2000 Amir Geva
GNU Library General Public License GNU Library General Public License
* Oriented bounding box derived from code originally written by
Jonathan Kreuzer
http://www.3dkingdoms.com/
No license given by original author; derived code under zlib license.
*************************************************************************** ***************************************************************************
Please do not redistribute the data files of the original game together Please do not redistribute the data files of the original game together
with this software. with this software.

69
localplayer.cpp Normal file
View File

@ -0,0 +1,69 @@
#include "localplayer.h"
#include "spritemanager.h"
namespace OpenGTA {
Pedestrian & PlayerController::getPed() {
return SpriteManagerHolder::Instance().getPed(playerId);
}
bool PlayerController::up(const uint32_t & key) {
if (!pc_ptr)
return false;
bool handled = false;
switch (key) {
case SDLK_LEFT:
pc_ptr->releaseTurnLeft();
handled = true;
break;
case SDLK_RIGHT:
pc_ptr->releaseTurnRight();
handled = true;
break;
case SDLK_UP:
pc_ptr->releaseMoveForward();
handled = true;
break;
case SDLK_DOWN:
pc_ptr->releaseMoveBack();
handled = true;
break;
case SDLK_LCTRL:
pc_ptr->releaseFireWeapon();
handled = true;
break;
default:
break;
}
return handled;
}
bool PlayerController::down(const uint32_t & key) {
if (!pc_ptr)
return false;
bool handled = false;
switch(key) {
case SDLK_LEFT:
handled = true;
break;
case SDLK_RIGHT:
handled = true;
break;
case SDLK_UP:
handled = true;
break;
case SDLK_DOWN:
handled = true;
break;
case SDLK_LCTRL:
handled = true;
break;
case SDLK_LSHIFT:
handled = true;
break;
default:
break;
}
return handled;
}
}

View File

@ -4,13 +4,21 @@
#include "game_objects.h" #include "game_objects.h"
#include "entity_controller.h" #include "entity_controller.h"
#include "id_sys.h" #include "id_sys.h"
#include "key_handler.h"
namespace OpenGTA { namespace OpenGTA {
class PlayerController { // : public PedController { //public Pedestrian::Controller { class PlayerController : public Util::KeyHandler {
public: public:
PlayerController() { PlayerController() {
reset();
}
void reset() {
playerId = TypeIdBlackBox::getPlayerId(); playerId = TypeIdBlackBox::getPlayerId();
cash = 0;
wantedLevel = 0;
modifier = 0;
numLives = 0;
pc_ptr = NULL; pc_ptr = NULL;
} }
PedController & getCtrl() { PedController & getCtrl() {
@ -20,8 +28,27 @@ namespace OpenGTA {
void setCtrl(PedController & pc) { void setCtrl(PedController & pc) {
pc_ptr = &pc; pc_ptr = &pc;
} }
void giveLives(uint16_t k) {
numLives += k;
}
void disableCtrl(bool soft);
void enableCtrl();
Pedestrian & getPed();
int32_t getNumLives() { return numLives; }
int32_t getWantedLevel() { return wantedLevel; }
uint32_t getCash() { return cash; }
bool up(const uint32_t & key);
bool down(const uint32_t & key);
uint32_t getId() { return playerId; }
void addCash(uint32_t v) { cash += v; }
void setWanted(int32_t v) { wantedLevel = v; }
void addWanted(uint32_t v) { wantedLevel += v; if (wantedLevel > 5) wantedLevel = 5; }
private: private:
uint32_t playerId; uint32_t playerId;
uint32_t cash;
int32_t wantedLevel;
uint32_t modifier;
int32_t numLives;
PedController * pc_ptr; PedController * pc_ptr;
}; };

View File

@ -1,3 +1,4 @@
#include <cassert>
#include "lua_ini_bridge.h" #include "lua_ini_bridge.h"
#include "log.h" #include "log.h"

150
lua_addon/lua_map.cpp Normal file
View File

@ -0,0 +1,150 @@
#include <cassert>
#include <sstream>
#include "lua_map.h"
#include "m_exceptions.h"
namespace OpenGTA {
namespace Script {
int Block::l_getBlockType(lua_State *L) {
lua_pushinteger(L, blockType());
return 1;
}
int Block::l_setBlockType(lua_State *L) {
uint8_t v = luaL_checkinteger(L, 1);
setBlockType(v);
return 0;
}
int Block::l_getSlopeType(lua_State *L) {
lua_pushinteger(L, slopeType());
return 1;
}
int Block::l_setSlopeType(lua_State *L) {
uint8_t v = luaL_checkinteger(L, 1);
setSlopeType(v);
return 0;
}
int Block::l_getRotation(lua_State *L) {
lua_pushinteger(L, rotation());
return 1;
}
int Block::l_setRotation(lua_State *L) {
uint8_t v = luaL_checkinteger(L, 1);
setRotation(v);
return 0;
}
int Block::l_getUpOk(lua_State *L) {
lua_pushboolean(L, upOk());
return 1;
}
int Block::l_getDownOk(lua_State *L) {
lua_pushboolean(L, downOk());
return 1;
}
int Block::l_getLeftOk(lua_State *L) {
lua_pushboolean(L, leftOk());
return 1;
}
int Block::l_getRightOk(lua_State *L) {
lua_pushboolean(L, rightOk());
return 1;
}
int Block::l_getIsFlat(lua_State *L) {
lua_pushboolean(L, isFlat());
return 1;
}
int Block::l_getRailway(lua_State *L) {
lua_pushboolean(L, railway());
return 1;
}
int Block::l_getRailStation(lua_State *L) {
lua_pushboolean(L, railStation());
return 1;
}
int Block::l_getRailStationTrain(lua_State *L) {
lua_pushboolean(L, railStationTrain());
return 1;
}
int Block::l_getTextureId(lua_State *L) {
int which = luaL_checkinteger(L, 1);
int v = 0;
if ((which < 0) || (which > 4)) {
std::ostringstream ostr;
ostr << "Quad id " << which << " is invalid";
throw E_OUTOFRANGE(ostr.str());
}
switch(which) {
case 0:
v = lid;
break;
case 1:
v = top;
break;
case 2:
v = bottom;
break;
case 3:
v = left;
break;
case 4:
v = right;
break;
default:
break;
// handled above
}
lua_pushinteger(L, v);
return 1;
}
int LMap::l_getBlockAt(lua_State *L) {
int x, y, z;
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
z = luaL_checkinteger(L, 3);
OpenGTA::Map::BlockInfo* bi = getBlockAtNew(x, y, z);
assert(bi);
Block* b = static_cast<Block*>(bi);
Lunar<Block>::push(L, b, false);
return 1;
}
int LMap::l_getNumBlocksAt(lua_State *L) {
int x, y;
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
lua_pushinteger(L, getNumBlocksAtNew(x, y));
return 1;
}
const char Block::className[] = "Block";
#define method(name) {#name, &Block::l_##name}
Lunar<Block>::RegType Block::methods[] = {
method(getBlockType),
method(getSlopeType),
method(getRotation),
method(getIsFlat),
method(getLeftOk),
method(getRightOk),
method(getUpOk),
method(getDownOk),
method(getRailway),
method(getRailStation),
method(getRailStationTrain),
method(getTextureId),
method(setBlockType),
method(setRotation),
method(setSlopeType),
{0, 0}
};
#undef method
#define method(name) {#name, &LMap::l_##name}
const char LMap::className[] = "Map";
Lunar<LMap>::RegType LMap::methods[] = {
method(getNumBlocksAt),
method(getBlockAt),
{0, 0}
};
}
}

50
lua_addon/lua_map.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef LUA_MAP_H
#define LUA_MAP_H
#include "lunar.h"
#include "opengta.h"
namespace OpenGTA {
namespace Script {
class Block : public OpenGTA::Map::BlockInfo {
public:
int l_getBlockType(lua_State *L);
int l_getUpOk(lua_State *L);
int l_getDownOk(lua_State *L);
int l_getLeftOk(lua_State *L);
int l_getRightOk(lua_State *L);
int l_getIsFlat(lua_State *L);
int l_getSlopeType(lua_State *L);
int l_getRotation(lua_State *L);
int l_getRailway(lua_State *L);
int l_getRailStation(lua_State *L);
int l_getRailStationTrain(lua_State *L);
int l_getTextureId(lua_State *L);
int l_setBlockType(lua_State *L);
int l_setUpOk(lua_State *L);
int l_setDownOk(lua_State *L);
int l_setLeftOk(lua_State *L);
int l_setRightOk(lua_State *L);
int l_setIsFlat(lua_State *L);
int l_setSlopeType(lua_State *L);
int l_setRotation(lua_State *L);
//...
int l_setTextureId(lua_State *L);
static const char className[];
static Lunar<Block>::RegType methods[];
};
class LMap : public OpenGTA::Map {
public:
LMap() : OpenGTA::Map("") {}
int l_getNumBlocksAt(lua_State *L);
int l_getBlockAt(lua_State *L);
static const char className[];
static Lunar<LMap>::RegType methods[];
};
}
}
#endif

View File

@ -11,6 +11,8 @@
using namespace Util; using namespace Util;
extern int global_Done;
namespace OpenGTA { namespace OpenGTA {
namespace Script { namespace Script {
LuaVM::LuaVM() : L(NULL) { LuaVM::LuaVM() : L(NULL) {
@ -20,6 +22,7 @@ namespace OpenGTA {
luaopen_base(L); luaopen_base(L);
luaopen_math(L); luaopen_math(L);
luaopen_table(L);
_registered = false; _registered = false;
lua_settop(L, 0); lua_settop(L, 0);
prepare(); prepare();
@ -31,17 +34,24 @@ namespace OpenGTA {
L = NULL; L = NULL;
} }
int vm_quit(lua_State *L) {
global_Done = true;
return 0;
}
void LuaVM::prepare() { void LuaVM::prepare() {
LGUARD(L); LGUARD(L);
if (!_registered) { if (!_registered) {
Lunar<Block>::Register2(L); Lunar<Block>::Register2(L);
Lunar<LMap>::Register2(L); Lunar<LMap>::Register2(L);
/* #ifndef LUA_MAP_ONLY
Lunar<CityView>::Register2(L); Lunar<CityView>::Register2(L);
luaL_openlib(L, "camera", Camera::methods, 0); luaL_openlib(L, "camera", Camera::methods, 0);
luaL_openlib(L, "screen", Screen::methods, 0); luaL_openlib(L, "screen", Screen::methods, 0);
luaL_openlib(L, "spritecache", SpriteCache::methods, 0); luaL_openlib(L, "spritecache", SpriteCache::methods, 0);
*/ #endif
lua_pushcfunction(L, vm_quit);
lua_setglobal(L, "quit");
} }
_registered = true; _registered = true;
} }
@ -61,15 +71,15 @@ namespace OpenGTA {
} }
void LuaVM::setCityView(OpenGTA::CityView & cv) { void LuaVM::setCityView(OpenGTA::CityView & cv) {
#ifndef LUA_MAP_ONLY
LGUARD(L); LGUARD(L);
/*
CityView *scv = static_cast<CityView*>(&cv); CityView *scv = static_cast<CityView*>(&cv);
lua_gettable(L, LUA_GLOBALSINDEX); lua_gettable(L, LUA_GLOBALSINDEX);
int scv_ref = Lunar<CityView>::push(L, scv, false); int scv_ref = Lunar<CityView>::push(L, scv, false);
lua_pushliteral(L, "city_view"); lua_pushliteral(L, "city_view");
lua_pushvalue(L, scv_ref); lua_pushvalue(L, scv_ref);
lua_settable(L, LUA_GLOBALSINDEX); lua_settable(L, LUA_GLOBALSINDEX);
*/ #endif
} }
void LuaVM::runString(const char* _str) { void LuaVM::runString(const char* _str) {
@ -103,7 +113,7 @@ namespace OpenGTA {
lua_getglobal(L, key); lua_getglobal(L, key);
if (!lua_isnumber(L, -1)) if (!lua_isnumber(L, -1))
throw E_SCRIPTERROR("Expected int value for key: " + std::string(key)); throw E_SCRIPTERROR("Expected int value for key: " + std::string(key));
int v = int(lua_tonumber(L, -1)); int v = int(lua_tointeger(L, -1));
return v; return v;
} }
@ -125,9 +135,69 @@ namespace OpenGTA {
return v; return v;
} }
bool LuaVM::getGlobalBool(const char* key) {
LGUARD(L);
lua_getglobal(L, key);
if (!lua_isboolean(L, -1))
throw E_SCRIPTERROR("Expected boolean value for key: " + std::string(key));
return lua_toboolean(L, -1);
}
void LuaVM::setInt(const char* key, int v) {
lua_pushinteger(L, v);
lua_setfield(L, -2, key);
}
int LuaVM::getInt(const char* key) {
LGUARD(L);
lua_getfield(L, -1, key);
if (!lua_isnumber(L, -1))
throw E_SCRIPTERROR("Expected int value for key: " + std::string(key));
return luaL_checkinteger(L, -1);
}
void LuaVM::setFloat(const char* key, float v) {
lua_pushnumber(L, v);
lua_setfield(L, -2, key);
}
float LuaVM::getFloat(const char* key) {
LGUARD(L);
lua_getfield(L, -1, key);
if (!lua_isnumber(L, -1))
throw E_SCRIPTERROR("Expected float value for key: " + std::string(key));
return luaL_checknumber(L, -1);
}
void LuaVM::setString(const char* key, const char* v) {
lua_pushstring(L, v);
lua_setfield(L, -2, key);
}
const char* LuaVM::getString(const char* key) {
LGUARD(L);
lua_getfield(L, -1, key);
if (!lua_isstring(L, -1))
throw E_SCRIPTERROR("Expected string value for key: " + std::string(key));
return luaL_checkstring(L, -1);
}
void LuaVM::setBool(const char* key, bool v) {
lua_pushboolean(L, v);
lua_setfield(L, -2, key);
}
bool LuaVM::getBool(const char* key) {
LGUARD(L);
lua_getfield(L, -1, key);
if (!lua_isboolean(L, -1))
throw E_SCRIPTERROR("Expected boolean value for key: " + std::string(key));
return lua_toboolean(L, -1);
}
void LuaVM::setGlobalInt(const char* key, int v) { void LuaVM::setGlobalInt(const char* key, int v) {
LGUARD(L); LGUARD(L);
lua_pushnumber(L, v); lua_pushinteger(L, v);
lua_setglobal(L, key); lua_setglobal(L, key);
} }
@ -143,5 +213,11 @@ namespace OpenGTA {
lua_setglobal(L, key); lua_setglobal(L, key);
} }
void LuaVM::setGlobalBool(const char* key, bool v) {
LGUARD(L);
lua_pushboolean(L, v);
lua_setglobal(L, key);
}
} }
} }

View File

@ -19,9 +19,21 @@ namespace OpenGTA {
int getGlobalInt(const char*); int getGlobalInt(const char*);
float getGlobalFloat(const char*); float getGlobalFloat(const char*);
const char* getGlobalString(const char*); const char* getGlobalString(const char*);
bool getGlobalBool(const char*);
void setGlobalInt(const char*, int); void setGlobalInt(const char*, int);
void setGlobalFloat(const char*, float); void setGlobalFloat(const char*, float);
void setGlobalString(const char*, const char*); void setGlobalString(const char*, const char*);
void setGlobalBool(const char*, bool);
void setInt(const char*, int);
int getInt(const char*);
void setFloat(const char*, float);
float getFloat(const char*);
void setString(const char*, const char*);
const char* getString(const char*);
void setBool(const char*, bool);
bool getBool(const char*);
lua_State *getInternalState(); lua_State *getInternalState();
protected: protected:
lua_State *L; lua_State *L;

View File

@ -1,6 +1,7 @@
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <unistd.h>
#include "m_exceptions.h" #include "m_exceptions.h"
#include "log.h" #include "log.h"
@ -11,6 +12,7 @@ extern void run_main();
int global_EC = 0; int global_EC = 0;
int global_Done = 0; int global_Done = 0;
int global_Restart = 0;
#ifndef DONT_CATCH #ifndef DONT_CATCH
bool catch_exceptions = true; bool catch_exceptions = true;
@ -54,5 +56,10 @@ int main(int argc, char* argv[]) {
} }
} }
if (global_Restart) {
on_exit();
execvp(argv[0], argv);
}
std::exit(0); std::exit(0);
} }

View File

@ -58,7 +58,8 @@ doxy_main.h: doc/hacking.txt tools/doxy_doc.sh
doxyclean: doxyclean:
$(RM) doxy_main.h -r doc/html $(RM) doxy_main.h -r doc/html
package: package: release_files_sorted
sh tools/cvslog.sh
(cd .. && tar jvcf ogta_src_`date +%F`.tar.bz2 -T ogta/release_files_sorted) (cd .. && tar jvcf ogta_src_`date +%F`.tar.bz2 -T ogta/release_files_sorted)
@echo "saved as: ogta_src_`date +%F.tar.bz2`" @echo "saved as: ogta_src_`date +%F.tar.bz2`"

View File

@ -1,4 +1,46 @@
/* Derived from code written by Jonathan Kreuzer.
*
* See: http://www.3dkingdoms.com/weekly/weekly.php?a=21
*
* basically the same as bbox.h/.cpp but using coldet math
*
* -- quote from a mail of the author --
*
* You're free to continue using my CBBox code however you want.
* ... [snip] ...
* The only thing I ask is a note about where it came from ( I think
* you said you added a link to the article, so that's fine. )
*
*/
/************************************************************************
* Copyright (c) 2005-2007 tok@openlinux.org.uk *
* *
* This software is provided as-is, without any express or implied *
* warranty. In no event will the authors be held liable for any *
* damages arising from the use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute *
* it freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must *
* not claim that you wrote the original software. If you use this *
* software in a product, an acknowledgment in the product documentation *
* would be appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must *
* not be misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source *
* distribution. *
************************************************************************/
#include <cassert>
#include "log.h"
#include "obox.h" #include "obox.h"
#include "plane.h"
// -------------------------- // --------------------------
// //
// Oriented Bounding Box Class // Oriented Bounding Box Class
@ -8,7 +50,7 @@
// //
// Check if a point is in this bounding box // Check if a point is in this bounding box
// //
bool OBox::IsPointInBox(const Vector3D &InP) const bool OBox::isPointInBox(const Vector3D &InP) const
{ {
// Rotate the point into the box's coordinates // Rotate the point into the box's coordinates
Vector3D P = Transform(InP, m_M.Inverse()); Vector3D P = Transform(InP, m_M.Inverse());
@ -23,7 +65,7 @@ bool OBox::IsPointInBox(const Vector3D &InP) const
// //
// Check if a sphere overlaps any part of this bounding box // Check if a sphere overlaps any part of this bounding box
// //
bool OBox::IsSphereInBox( const Vector3D &InP, float fRadius) const bool OBox::isSphereInBox( const Vector3D &InP, float fRadius) const
{ {
float fDist; float fDist;
float fDistSq = 0; float fDistSq = 0;
@ -44,7 +86,7 @@ bool OBox::IsSphereInBox( const Vector3D &InP, float fRadius) const
// //
// Check if the bounding box is completely behind a plane( defined by a normal and a point ) // Check if the bounding box is completely behind a plane( defined by a normal and a point )
// //
bool OBox::BoxOutsidePlane( const Vector3D &InNorm, const Vector3D &InP ) const bool OBox::boxOutsidePlane( const Vector3D &InNorm, const Vector3D &InP ) const
{ {
// Plane Normal in Box Space // Plane Normal in Box Space
Vector3D Norm = rotateVector(InNorm, m_M.Inverse() ); Vector3D Norm = rotateVector(InNorm, m_M.Inverse() );
@ -52,7 +94,7 @@ bool OBox::BoxOutsidePlane( const Vector3D &InNorm, const Vector3D &InP ) const
float Extent = Norm * m_Extent; //Norm.Dot( m_Extent ); // Box Extent along the plane normal float Extent = Norm * m_Extent; //Norm.Dot( m_Extent ); // Box Extent along the plane normal
//float Distance = InNorm.Dot( GetCenterPoint() - InP ); // Distance from Box Center to the Plane //float Distance = InNorm.Dot( GetCenterPoint() - InP ); // Distance from Box Center to the Plane
float Distance = InNorm * (GetCenterPoint() - InP); float Distance = InNorm * (getCenterPoint() - InP);
// If Box Centerpoint is behind the plane further than its extent, the Box is outside the plane // If Box Centerpoint is behind the plane further than its extent, the Box is outside the plane
if ( Distance < -Extent ) return true; if ( Distance < -Extent ) return true;
@ -62,7 +104,7 @@ bool OBox::BoxOutsidePlane( const Vector3D &InNorm, const Vector3D &InP ) const
// //
// Does the Line (L1, L2) intersect the Box? // Does the Line (L1, L2) intersect the Box?
// //
bool OBox::IsLineInBox( const Vector3D& L1, const Vector3D& L2 ) const bool OBox::isLineInBox( const Vector3D& L1, const Vector3D& L2 ) const
{ {
// Put line in box space // Put line in box space
Matrix3D MInv = m_M.Inverse(); Matrix3D MInv = m_M.Inverse();
@ -87,10 +129,40 @@ bool OBox::IsLineInBox( const Vector3D& L1, const Vector3D& L2 ) const
return true; return true;
} }
void OBox::lineCrossBox(const Vector3D& L1, const Vector3D& L2, Vector3D & isecLocal) const {
// Put line in box space
Matrix3D MInv = m_M.Inverse();
Vector3D LB1 = Transform(L1, MInv);
Vector3D LB2 = Transform(L2, MInv);
float small_t = 2.0f;
Vector3D p_copy(0, 0, 0);
//i = 0: -x,-z <-> -x,z
//i = 1: -x,-z <-> x,-z
//i = 2: x,-z, <-> x,z
//i = 3: -x,z <-> x,z
for (int i = 0; i < 4; i++) {
Vector3D s1((i <= 1 || i == 3 ? -m_Extent.x : m_Extent.x), 0, (i < 3 ? -m_Extent.z : m_Extent.z));
Vector3D s2((i == 0 ? -m_Extent.x : m_Extent.x), 0, (i == 1 ? -m_Extent.z : m_Extent.z));
Vector3D p;
float dt = Math::intersection_segments(s1, s2, LB1, LB2, p);
if ((dt >= 0.0f) && (dt < small_t)) {
p_copy = p;
small_t = dt;
}
}
if (small_t >= 0.0f && small_t <= 1.0f) {
isecLocal = p_copy;
return;
}
ERROR << "Did not find intersection when OBB says there is one :-(" << std::endl;
isecLocal = L1;
}
// //
// Returns a 3x3 rotation matrix as vectors // Returns a 3x3 rotation matrix as vectors
// //
inline void OBox::GetInvRot( Vector3D *pvRot ) const inline void OBox::getInvRot( Vector3D *pvRot ) const
{ {
pvRot[0] = Vector3D( m_M.m[0][0], m_M.m[0][1], m_M.m[0][2] ); pvRot[0] = Vector3D( m_M.m[0][0], m_M.m[0][1], m_M.m[0][2] );
pvRot[1] = Vector3D( m_M.m[1][0], m_M.m[1][1], m_M.m[1][2] ); pvRot[1] = Vector3D( m_M.m[1][0], m_M.m[1][1], m_M.m[1][2] );
@ -101,13 +173,13 @@ inline void OBox::GetInvRot( Vector3D *pvRot ) const
// Check if any part of a box is inside any part of another box // Check if any part of a box is inside any part of another box
// Uses the separating axis test. // Uses the separating axis test.
// //
bool OBox::IsBoxInBox( OBox &BBox ) const bool OBox::isBoxInBox( OBox &BBox ) const
{ {
Vector3D SizeA = m_Extent; Vector3D SizeA = m_Extent;
Vector3D SizeB = BBox.m_Extent; Vector3D SizeB = BBox.m_Extent;
Vector3D RotA[3], RotB[3]; Vector3D RotA[3], RotB[3];
GetInvRot( RotA ); getInvRot( RotA );
BBox.GetInvRot( RotB ); BBox.getInvRot( RotB );
float R[3][3]; // Rotation from B to A float R[3][3]; // Rotation from B to A
float AR[3][3]; // absolute values of R matrix, to use with box extents float AR[3][3]; // absolute values of R matrix, to use with box extents
@ -123,7 +195,7 @@ bool OBox::IsBoxInBox( OBox &BBox ) const
} }
// Vector separating the centers of Box B and of Box A // Vector separating the centers of Box B and of Box A
Vector3D vSepWS = BBox.GetCenterPoint() - GetCenterPoint(); Vector3D vSepWS = BBox.getCenterPoint() - getCenterPoint();
// Rotated into Box A's coordinates // Rotated into Box A's coordinates
Vector3D vSepA( vSepWS * RotA[0], vSepWS * RotA[1], vSepWS * RotA[2] ); Vector3D vSepA( vSepWS * RotA[0], vSepWS * RotA[1], vSepWS * RotA[2] );

View File

@ -1,43 +1,79 @@
/* Derived from code written by Jonathan Kreuzer.
*
* See: http://www.3dkingdoms.com/weekly/weekly.php?a=21
*
* basically the same as bbox.h/.cpp but using coldet math
*
* -- quote from a mail of the author --
*
* You're free to continue using my CBBox code however you want.
* ... [snip] ...
* The only thing I ask is a note about where it came from ( I think
* you said you added a link to the article, so that's fine. )
*
*/
/************************************************************************
* Copyright (c) 2005-2007 tok@openlinux.org.uk *
* *
* This software is provided as-is, without any express or implied *
* warranty. In no event will the authors be held liable for any *
* damages arising from the use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute *
* it freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must *
* not claim that you wrote the original software. If you use this *
* software in a product, an acknowledgment in the product documentation *
* would be appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must *
* not be misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source *
* distribution. *
************************************************************************/
#include "math3d.h" #include "math3d.h"
// see: from: http://www.3dkingdoms.com/weekly/weekly.php?a=21
// basically the same as bbox.h/.cpp but using coldet math
class OBox class OBox
{ {
public: public:
OBox() {} OBox() {}
OBox( const Matrix3D & m, const Vector3D & extent ) OBox( const Matrix3D & m, const Vector3D & extent )
{ Set( m, extent ); } { set( m, extent ); }
OBox( const Matrix3D & m, const Vector3D & low, const Vector3D & high ) OBox( const Matrix3D & m, const Vector3D & low, const Vector3D & high )
{ Set( m, low, high ); } { set( m, low, high ); }
OBox( const OBox & other) OBox( const OBox & other)
{ Set( other.m_M, other.m_Extent ); } { set( other.m_M, other.m_Extent ); }
void Set( const Matrix3D & m, const Vector3D & extent ) void set( const Matrix3D & m, const Vector3D & extent )
{ {
m_M = m; m_M = m;
m_Extent = extent; m_Extent = extent;
} }
void Set( const Matrix3D & m, const Vector3D & low, const Vector3D & high ) void set( const Matrix3D & m, const Vector3D & low, const Vector3D & high )
{ {
m_M = m; m_M = m;
m_M.Translate( 0.5f * (low + high) ); m_M.Translate( 0.5f * (low + high) );
m_Extent = 0.5f * (high - low); m_Extent = 0.5f * (high - low);
} }
Vector3D GetSize() const Vector3D getSize() const
{ return 2.0f * m_Extent; } { return 2.0f * m_Extent; }
Vector3D GetCenterPoint() const Vector3D getCenterPoint() const
{ return m_M.GetTranslate(); } { return m_M.GetTranslate(); }
void GetInvRot( Vector3D *pvRot ) const; void getInvRot( Vector3D *pvRot ) const;
bool IsPointInBox( const Vector3D & p ) const ; bool isPointInBox( const Vector3D & p ) const ;
bool IsBoxInBox( OBox & box ) const ; bool isBoxInBox( OBox & box ) const ;
bool IsSphereInBox( const Vector3D & p, float fRadius ) const ; bool isSphereInBox( const Vector3D & p, float fRadius ) const ;
bool IsLineInBox( const Vector3D & l1, const Vector3D & l2 ) const ; bool isLineInBox( const Vector3D & l1, const Vector3D & l2 ) const ;
bool BoxOutsidePlane( const Vector3D & normal, const Vector3D & p ) const ; bool boxOutsidePlane( const Vector3D & normal, const Vector3D & p ) const ;
void lineCrossBox(const Vector3D & l1, const Vector3D & l2, Vector3D & isecLocalSpace) const;
// Data // Data
Matrix3D m_M; Matrix3D m_M;

74
math/plane.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "plane.h"
#include "log.h"
namespace Math {
// see: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/example.cpp
float intersection_segments(const Vector3D & s1, const Vector3D & s2,
const Vector3D & l1, const Vector3D & l2, Vector3D & hit) {
float denom = (l2.z - l1.z) * (s2.x - s1.x) -
(l2.x - l1.x) * (s2.z - s1.z);
float d_a = (l2.x - l1.x) * (s1.z - l1.z) -
(l2.z - l1.z) * (s1.x - l1.x);
float d_b = (s2.x - s1.x) * (s1.z - l1.z) -
(s2.z - s1.z) * (s1.x - l1.x);
float ua = d_a / denom; // ratio on s1 -> s2
float ub = d_b / denom; // ratio on l1 -> l2
if (denom == 0.0f) {
/*
if (d_a == 0.0f && d_b == 0.0f)
INFO << "COINCIDENT" << std::endl;
else
INFO << "PARALLEL" << std::endl;
*/
return -1.0f;
}
if (ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f) {
hit.x = s1.x + ua * (s2.x - s1.x);
hit.z = s1.z + ua * (s2.z - s1.z);
//INFO << "INTERSECTING " << hit.x << " " << hit.z << std::endl;
//INFO << ua << " | " << ub << std::endl;
return ub;
}
//INFO << "NOT INTERSECTING" << std::endl;
return -1.0f;
}
int Plane::segmentIntersect(const Vector3D & p1, const Vector3D & p2, Vector3D & p_p) {
float d = - normal.x * pop.x - normal.y * pop.y - normal.z * pop.z;
float denom = normal.x * (p2.x - p1.x) + normal.y * (p2.y - p1.y) +
normal.z * (p2.z - p1.z);
if (fabs(denom) < 0.001f)
return false;
float mu = - (d + normal.x * p1.x + normal.y * p1.y + normal.z * p1.z) / denom;
p_p = Vector3D(p2 - p1) * mu + p1;
if (mu < 0 || mu > 1)
return false;
return true;
}
float Plane::distance(const Vector3D & p) {
float d = normal * p;
d += - normal.x * pop.x - normal.y * pop.y - normal.z * pop.z;
return d;
}
}
/*
int main() {
Vector3D p(0, 0, 0);
Vector3D n(-1, 0, 0);
Math::Plane plane(p, n);
Vector3D p1(-1, 0, 0);
Vector3D p2(1, 0, 0);
Vector3D col;
if (plane.segmentIntersect(p1, p2, col))
std::cout << "intersect at: " << col.x << " " << col.y << " " << col.z << std::endl;
std::cout << plane.distance(p1) << std::endl;
std::cout << plane.distance(p2) << std::endl;
}
*/

26
math/plane.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef MATH_PLANE_H
#define MATH_PLANE_H
#include "math3d.h"
namespace Math {
float intersection_segments(const Vector3D & s1, const Vector3D & s2,
const Vector3D & l1, const Vector3D & l2, Vector3D & hit);
struct Plane {
Plane(const Vector3D & p, const Vector3D & n) :
pop(p), normal(n) {}
Plane(const Vector3D & p1, const Vector3D & p2, const Vector3D & p3) :
pop(p1), normal() {
const Vector3D pa(p2 - p1);
const Vector3D pb(p3 - p1);
normal = CrossProduct(pa, pb).Normalized();
}
Vector3D pop;
Vector3D normal;
int segmentIntersect(const Vector3D & p1, const Vector3D & p2, Vector3D & p_p);
float distance(const Vector3D & p);
};
}
#endif

View File

@ -100,28 +100,48 @@ namespace OpenGTA {
return ""; return "";
std::string n; std::string n;
if (lastSubLocation == 0) if (lastSubLocation == 0)
n.append("Central "); //n.append("Central ");
n.append(_c);
else if (lastSubLocation == 1) else if (lastSubLocation == 1)
n.append("North "); //n.append("North ");
n.append(_n);
else if (lastSubLocation == 2) else if (lastSubLocation == 2)
n.append("South "); n.append(_s);
//n.append("South ");
else if (lastSubLocation == 4) else if (lastSubLocation == 4)
n.append("East "); n.append(_e);
//n.append("East ");
else if (lastSubLocation == 8) else if (lastSubLocation == 8)
n.append("West "); n.append(_w);
//n.append("West ");
else if (lastSubLocation == 9) else if (lastSubLocation == 9)
n.append("Northwest "); n.append(_nw);
//n.append("Northwest ");
else if (lastSubLocation == 10) else if (lastSubLocation == 10)
n.append("Southwest "); n.append(_sw);
//n.append("Southwest ");
else if (lastSubLocation == 5) else if (lastSubLocation == 5)
n.append("Northeast "); n.append(_ne);
//n.append("Northeast ");
else if (lastSubLocation == 6) else if (lastSubLocation == 6)
n.append("Southeast "); n.append(_se);
//n.append("Southeast ");
n.append(" ");
n.append(name); n.append(name);
return n.c_str(); return n.c_str();
} }
std::string NavData::_c;
std::string NavData::_n;
std::string NavData::_s;
std::string NavData::_w;
std::string NavData::_e;
std::string NavData::_nw;
std::string NavData::_ne;
std::string NavData::_sw;
std::string NavData::_se;
NavData::NavData(PHYSFS_uint32 size, PHYSFS_file *fd, const size_t level_num) { NavData::NavData(PHYSFS_uint32 size, PHYSFS_file *fd, const size_t level_num) {
if (size % 35) { if (size % 35) {
std::ostringstream o; std::ostringstream o;
@ -133,6 +153,15 @@ namespace OpenGTA {
assert(fd); assert(fd);
MessageDB & msg = MainMsgHolder::Instance().get(); MessageDB & msg = MainMsgHolder::Instance().get();
_c =msg.getText("c");
_n = msg.getText("n");
_s = msg.getText("s");
_w = msg.getText("w");
_e = msg.getText("e");
_nw = msg.getText("nw");
_ne = msg.getText("ne");
_sw = msg.getText("sw");
_se = msg.getText("se");
for (PHYSFS_uint32 i = 0; i < c; ++i) { for (PHYSFS_uint32 i = 0; i < c; ++i) {
Sector *sec = new Sector(fd); Sector *sec = new Sector(fd);
if (sec->getSize() == 0) { // workaround for 'NYC.CMP' (empty sectors) if (sec->getSize() == 0) { // workaround for 'NYC.CMP' (empty sectors)

View File

@ -89,6 +89,7 @@ namespace OpenGTA {
NavData(PHYSFS_uint32 size, PHYSFS_file *fd, const size_t level_num); NavData(PHYSFS_uint32 size, PHYSFS_file *fd, const size_t level_num);
~NavData(); ~NavData();
Sector* getSectorAt(PHYSFS_uint8, PHYSFS_uint8); Sector* getSectorAt(PHYSFS_uint8, PHYSFS_uint8);
static std::string _c, _n, _s, _w, _e, _nw, _ne, _sw, _se;
private: private:
void clear(); void clear();
typedef std::multimap<PHYSFS_uint16, Sector*> SectorMapType; typedef std::multimap<PHYSFS_uint16, Sector*> SectorMapType;

View File

@ -1 +1 @@
2007-04-16 2007-06-14

View File

@ -27,6 +27,7 @@ namespace OpenGTA {
public: public:
GraphicsBase(); GraphicsBase();
virtual ~GraphicsBase(); virtual ~GraphicsBase();
uint8_t getFormat();
typedef struct ObjectInfo { typedef struct ObjectInfo {
PHYSFS_uint32 width, height, depth; PHYSFS_uint32 width, height, depth;
@ -399,11 +400,15 @@ namespace OpenGTA {
inline bool downOk() { return (typeMap & 2); } inline bool downOk() { return (typeMap & 2); }
inline bool leftOk() { return (typeMap & 4); } inline bool leftOk() { return (typeMap & 4); }
inline bool rightOk() { return (typeMap & 8); } inline bool rightOk() { return (typeMap & 8); }
inline uint8_t blockType() { return ((typeMap & 16 ? 1 : 0) + (typeMap & 32 ? 2 : 0) + (typeMap & 64 ? 4 : 0)); } inline uint8_t blockType() { return ((typeMap & 16 ? 1 : 0) +
(typeMap & 32 ? 2 : 0) + (typeMap & 64 ? 4 : 0)); }
inline bool isFlat() { return (typeMap & 128); } inline bool isFlat() { return (typeMap & 128); }
inline uint8_t slopeType() { return ((typeMap & 256 ? 1 : 0) + (typeMap & 512 ? 2 : 0) + inline uint8_t slopeType() { return ((typeMap & 256 ? 1 : 0) +
(typeMap & 1024 ? 4 : 0) + (typeMap & 2048 ? 8 : 0) + (typeMap & 4096 ? 16 : 0) + (typeMap & 8192 ? 32 : 0));} (typeMap & 512 ? 2 : 0) + (typeMap & 1024 ? 4 : 0) +
inline uint8_t rotation() { return ((typeMap & 16384 ? 1 : 0) + (typeMap & 32768 ? 2 : 0)); } (typeMap & 2048 ? 8 : 0) + (typeMap & 4096 ? 16 : 0) +
(typeMap & 8192 ? 32 : 0)); }
inline uint8_t rotation() { return ((typeMap & 16384 ? 1 : 0) +
(typeMap & 32768 ? 2 : 0)); }
/* m1win seems to indicate: /* m1win seems to indicate:
* 000 - Nothing * 000 - Nothing
* 001 - traffic lights * 001 - traffic lights
@ -414,6 +419,16 @@ namespace OpenGTA {
* 110 - railway station * 110 - railway station
* 111 - railway station train * 111 - railway station train
*/ */
inline void setUpOk(bool v) { if (v) typeMap |= 1; else typeMap &= ~1; }
inline void setDownOk(bool v) { if (v) typeMap |= 2; else typeMap &= ~2; }
inline void setLeftOk(bool v) { if (v) typeMap |= 4; else typeMap &= ~4; }
inline void setRightOk(bool v) { if (v) typeMap |= 8; else typeMap &= ~8; }
inline void setIsFlat(bool v) { if (v) typeMap |= 128; else typeMap &= ~128; }
void setBlockType(uint8_t v);
void setSlopeType(uint8_t v);
void setRotation(uint8_t v);
inline bool trafficLights() { return (typeMapExt & 1); } inline bool trafficLights() { return (typeMapExt & 1); }
inline bool railEndTurn() { return (typeMapExt & 4); } inline bool railEndTurn() { return (typeMapExt & 4); }
inline bool railStartTurn() { return ((typeMapExt & 4) && (typeMapExt &1)); } inline bool railStartTurn() { return ((typeMapExt & 4) && (typeMapExt &1)); }
@ -450,6 +465,8 @@ namespace OpenGTA {
NavData *nav; NavData *nav;
ObjectPosition *objects; ObjectPosition *objects;
PHYSFS_uint16 numObjects; PHYSFS_uint16 numObjects;
const Location & getNearestLocationByType(uint8_t t, uint8_t x, uint8_t y);
const LocationMap & getLocationMap() { return locations; }
protected: protected:
PHYSFS_uint32 base[GTA_MAP_MAXDIMENSION][GTA_MAP_MAXDIMENSION]; PHYSFS_uint32 base[GTA_MAP_MAXDIMENSION][GTA_MAP_MAXDIMENSION];

View File

@ -13,7 +13,7 @@ function program_exists() {
function print_make_file_list() { function print_make_file_list() {
FOO=GL_SRC FOO=GL_SRC
FOOO=GL_OBJ FOOO=GL_OBJ
( grep -l "^namespace OpenGL" *.cpp ;echo "gl_frustum.cpp";echo "math/obox.cpp coldet/math3d.cpp util/physfsrwops.c" ) | sort | xargs echo "$FOO =" ( grep -l "^namespace OpenGL" *.cpp ;echo "gl_frustum.cpp";echo "math/obox.cpp math/plane.cpp coldet/math3d.cpp util/physfsrwops.c" ) | sort | xargs echo "$FOO ="
echo "$FOOO = \${$FOO:.cpp=.o}" echo "$FOOO = \${$FOO:.cpp=.o}"
FOO=OGTA_SRC FOO=OGTA_SRC
FOOO=OGTA_OBJ FOOO=OGTA_OBJ
@ -71,9 +71,9 @@ viewer${EXE_PFIX}: main2.cpp viewer.o \$(OGTA_OBJ) \$(GL_OBJ) \$(UTIL_OBJ) \$(OS
-o \$@ \$+ \\ -o \$@ \$+ \\
\$(SDL_LIB) \$(SDL_GL_LIB) \$(PHYSFS_LIB) \$(LOKI_LIB) \$(COLDET_LIB) \$(SDL_LIB) \$(SDL_GL_LIB) \$(PHYSFS_LIB) \$(LOKI_LIB) \$(COLDET_LIB)
luaviewer${EXE_PFIX}: main2.cpp viewer.cpp \$(OGTA_OBJ) \$(GL_OBJ) \$(UTIL_OBJ) \$(OSTEER_OBJ) \ luaviewer${EXE_PFIX}: main2.cpp viewer.o \$(OGTA_OBJ) \$(GL_OBJ) \$(UTIL_OBJ) \$(OSTEER_OBJ) \
\$(LUA_OBJ) \$(LUA_OBJ)
\$(CXX) \$(CATCH_E) -DWITH_LUA \$(FLAGS) \$(DEFS) \\ \$(CXX) \$(CATCH_E) \$(FLAGS) \$(DEFS) \\
\$(INC) \\ \$(INC) \\
-o \$@ \$+ \\ -o \$@ \$+ \\
\$(SDL_LIB) \$(SDL_GL_LIB) \$(PHYSFS_LIB) \$(LOKI_LIB) \$(COLDET_LIB) \$(LUA_LIB) \$(SDL_LIB) \$(SDL_GL_LIB) \$(PHYSFS_LIB) \$(LOKI_LIB) \$(COLDET_LIB) \$(LUA_LIB)
@ -89,6 +89,11 @@ slopeview: main.o tools/display_slopes.o navdata.o read_cmp.o \
\$(UTIL_OBJ) common_sdl_gl.o \$(UTIL_OBJ) common_sdl_gl.o
\$(CXX) \$(CXXFLAGS) -o \$@ \$+ \$(SDL_LIB) \$(PHYSFS_LIB) -lSDL_image \$(CXX) \$(CXXFLAGS) -o \$@ \$+ \$(SDL_LIB) \$(PHYSFS_LIB) -lSDL_image
blockview: main2.o tools/blockview.cpp util/log.o util/m_exceptions.o \
gl_camera.o gl_screen.o read_cmp.o dataholder.o slope_height_func.o navdata.o \
datahelper.o read_gry.o read_g24.o util/set.o util/buffercache.o read_fxt.o blockdata.o
\$(CXX) \$(CXXFLAGS) -o \$@ \$+ \$(SDL_LIB) \$(SDL_GL_LIB) \$(PHYSFS_LIB)
g24: read_g24.cpp read_gry.o \$(UTIL_OBJ) g24: read_g24.cpp read_gry.o \$(UTIL_OBJ)
\$(CXX) -DG24_DUMPER \$(CXXFLAGS) -o \$@ \$+ \$(SDL_LIB) \$(PHYSFS_LIB) \$(CXX) -DG24_DUMPER \$(CXXFLAGS) -o \$@ \$+ \$(SDL_LIB) \$(PHYSFS_LIB)
@ -305,6 +310,8 @@ OPT = $OPT
WARN = $WARN WARN = $WARN
DEFS = $DEFS DEFS = $DEFS
LIB_RT_PATH = libs
# def only for 'main' programs to let gdb handle the exception # def only for 'main' programs to let gdb handle the exception
#CATCH_E = -DDONT_CATCH #CATCH_E = -DDONT_CATCH
@ -312,7 +319,7 @@ DEFS = $DEFS
# the external libraries # the external libraries
PHYSFS_INC = -Iinc PHYSFS_INC = -Iinc
PHYSFS_LIB = -Llibs -lphysfs -lz PHYSFS_LIB = -Llibs -lphysfs-1-1-0 -lzlib1
SDL_INC = -Iinc -D_GNU_SOURCE=1 -D_REENTRANT SDL_INC = -Iinc -D_GNU_SOURCE=1 -D_REENTRANT
SDL_LIB = -Llibs -lSDLmain -lSDL SDL_LIB = -Llibs -lSDLmain -lSDL
@ -379,17 +386,28 @@ function print_config_h() {
#define DEFAULT_SCREEN_WIDTH 640 #define DEFAULT_SCREEN_WIDTH 640
#define DEFAULT_SCREEN_HEIGHT 480 #define DEFAULT_SCREEN_HEIGHT 480
// 0 - no vsync (default), 1 - try to use SDL_GL_SWAP_CONTROL,
// 2 - try native call (GLX on linux, unsupported on win32)
//#undef DEFAULT_SCREEN_VSYNC
#define DEFAULT_SCREEN_VSYNC 2
// default pathes; env-variables can override
#define OGTA_DEFAULT_DATA_PATH "gtadata.zip" #define OGTA_DEFAULT_DATA_PATH "gtadata.zip"
#define OGTA_DEFAULT_MOD_PATH "" #define OGTA_DEFAULT_MOD_PATH ""
#define OGTA_DEFAULT_HOME_PATH PHYSFS_getBaseDir() #define OGTA_DEFAULT_HOME_PATH PHYSFS_getBaseDir()
// just for fun
#define USED_GCC_VERSION "$GCC_VERSION" #define USED_GCC_VERSION "$GCC_VERSION"
// enable features // enable features
#define DO_SCALEX #define DO_SCALE2X
#undef WITH_LUA
$SDL_SOUND_MIXER $SDL_SOUND_MIXER
$SDL_GL_SWAP_CONTROL $SDL_GL_SWAP_CONTROL
// use escape sequences to mark Log::info/warn/error()
#ifdef LINUX
//#define LOG_USE_ANSI_COLORS
#endif
EOF EOF
} }
@ -401,6 +419,7 @@ if [[ -n "$1" && "$1" != "LINUX" ]]; then
print_w32settings > src_list.make print_w32settings > src_list.make
print_make_file_list >> src_list.make print_make_file_list >> src_list.make
print_target_list >> src_list.make print_target_list >> src_list.make
SDL_GL_SWAP_CONTROL='#define HAVE_SDL_VSYNC'
else else
OGTA_PLATFORM="LINUX" OGTA_PLATFORM="LINUX"
echo "*** LINUX ***" echo "*** LINUX ***"

View File

@ -22,6 +22,70 @@
*/ */
namespace OpenGTA { namespace OpenGTA {
void Map::BlockInfo::setBlockType(uint8_t v) {
switch(v) {
case 0:
typeMap &= ~(16 | 32 | 64);
break;
case 1:
typeMap |= 16;
typeMap &= ~(32 | 64);
break;
case 2:
typeMap |= 32;
typeMap &= ~(16 | 64);
break;
case 3:
typeMap |= (16 | 32);
typeMap &= ~64;
break;
case 4:
typeMap |= 64;
typeMap &= ~(16 | 32);
break;
case 5:
typeMap |= (16 | 64);
typeMap &= ~32;
break;
case 6:
typeMap |= (32 | 64);
typeMap &= ~16;
break;
case 7:
typeMap |= (16 | 32 | 64);
break;
default:
ERROR << "Invalid block-type: " << int(v) << std::endl;
break;
}
}
void Map::BlockInfo::setSlopeType(uint8_t v) {
WARN << "NOT IMPLEMENTED" << std::endl;
}
void Map::BlockInfo::setRotation(uint8_t v) {
switch(v) {
case 0:
typeMap &= ~(16384 | 32768);
break;
case 1:
typeMap |= 16384;
typeMap &= ~32768;
break;
case 2:
typeMap |= 32768;
typeMap &= ~16384;
break;
case 3:
typeMap |= (16384 | 32768);
break;
default:
ERROR << "Invalid rotation: " << int(v) << std::endl;
break;
}
}
Map::Map(const std::string& filename) { Map::Map(const std::string& filename) {
nav = 0; nav = 0;
fd = PHYSFS_openRead(filename.c_str()); fd = PHYSFS_openRead(filename.c_str());
@ -204,6 +268,7 @@ namespace OpenGTA {
PHYSFS_read(fd, static_cast<void*>(&loc.x), 1, 1); PHYSFS_read(fd, static_cast<void*>(&loc.x), 1, 1);
PHYSFS_read(fd, static_cast<void*>(&loc.y), 1, 1); PHYSFS_read(fd, static_cast<void*>(&loc.y), 1, 1);
PHYSFS_read(fd, static_cast<void*>(&loc.z), 1, 1); PHYSFS_read(fd, static_cast<void*>(&loc.z), 1, 1);
// skip dummy entries at 0,0,0
if ((loc.x == 0) && (loc.y == 0) && (loc.z == 0)) if ((loc.x == 0) && (loc.y == 0) && (loc.z == 0))
continue; continue;
if (i < 6) if (i < 6)
@ -266,6 +331,32 @@ namespace OpenGTA {
} }
} }
} }
const Map::Location & Map::getNearestLocationByType(uint8_t t, uint8_t x, uint8_t y) {
INFO << int(t) << " at " << int(x) << " " << int(y) << std::endl;
LocationMap::iterator i = locations.find(t);
LocationMap::iterator j;
if (i == locations.end()) {
std::ostringstream o;
o << "location-type " << int(t) << " not found in map";
throw E_UNKNOWNKEY(o.str());
}
int _x(x);
int _y(y);
int min_d = 255 * 255;
#define ABS(a) (a > 0 ? a : -a)
while (i != locations.end()) {
INFO << int(i->first) << ": "<< int(i->second->x) << " " << int(i->second->y) << std::endl;
int d = ABS((_x - i->second->x)) + ABS((_y - i->second->y));
if (d < min_d) {
min_d = d;
j = i;
}
}
#undef ABS
return *j->second;
}
} }
#if 0 #if 0

View File

@ -77,6 +77,9 @@ namespace OpenGTA {
//std::cout << tmp << " : " << buff << std::endl; //std::cout << tmp << " : " << buff << std::endl;
/*else /*else
std::cout << "Skipping: " << tmp << ": " << buff << std::endl;*/ std::cout << "Skipping: " << tmp << ": " << buff << std::endl;*/
#ifdef FXT_TEST
std::cout << tmp << " : " << buff << std::endl;
#endif
} }
else { else {
buff[i] = v; buff[i] = v;
@ -122,11 +125,19 @@ namespace OpenGTA {
} }
#if FXT_TEST #if FXT_TEST
#include "file_helper.h"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
PHYSFS_init(argv[0]); PHYSFS_init(argv[0]);
PHYSFS_addToSearchPath("gtadata.zip", 1); PHYSFS_addToSearchPath("gtadata.zip", 1);
OpenGTA::MessageDB* strings = new OpenGTA::MessageDB(); const char* lang = getenv("OGTA_LANG");
if (!lang)
lang = getenv("LANG");
if (!lang)
lang = "en";
OpenGTA::MessageDB* strings = new OpenGTA::MessageDB(
Util::FileHelper::lang2MsgFilename(lang)
);
std::cout << strings->getText(1001) << std::endl; std::cout << strings->getText(1001) << std::endl;
delete strings; delete strings;

View File

@ -279,6 +279,15 @@ namespace OpenGTA {
return _type; return _type;
} }
uint8_t GraphicsBase::getFormat() {
if (_topHeaderSize == 52)
return 0;
else if (_topHeaderSize == 64)
return 1;
throw E_INVALIDFORMAT("graphics-base header size");
return 255;
}
Graphics8Bit::Graphics8Bit(const std::string& style) : GraphicsBase() { Graphics8Bit::Graphics8Bit(const std::string& style) : GraphicsBase() {
fd = PHYSFS_openRead(style.c_str()); fd = PHYSFS_openRead(style.c_str());
if (fd == NULL) { if (fd == NULL) {
@ -344,8 +353,6 @@ namespace OpenGTA {
"#object-info: " << objectInfos.size() << " #car-info: " << carInfos.size() << std::endl; "#object-info: " << objectInfos.size() << " #car-info: " << carInfos.size() << std::endl;
} }
void Graphics8Bit::loadHeader() { void Graphics8Bit::loadHeader() {
PHYSFS_uint32 vc; PHYSFS_uint32 vc;
PHYSFS_readULE32(fd, &vc); PHYSFS_readULE32(fd, &vc);
@ -600,8 +607,8 @@ namespace OpenGTA {
} }
for (int i=0; i < car->numDoors; i++) { for (int i=0; i < car->numDoors; i++) {
PHYSFS_readSLE16(fd, &car->door[i].rpx);
PHYSFS_readSLE16(fd, &car->door[i].rpy); PHYSFS_readSLE16(fd, &car->door[i].rpy);
PHYSFS_readSLE16(fd, &car->door[i].rpx);
PHYSFS_readSLE16(fd, &car->door[i].object); PHYSFS_readSLE16(fd, &car->door[i].object);
PHYSFS_readSLE16(fd, &car->door[i].delta); PHYSFS_readSLE16(fd, &car->door[i].delta);
bytes_read += 4 * 2; bytes_read += 4 * 2;
@ -777,14 +784,26 @@ namespace OpenGTA {
const unsigned int b_offset = 256 * info.yoffset + info.xoffset; const unsigned int b_offset = 256 * info.yoffset + info.xoffset;
if (delta_is_a_set) { if (delta_is_a_set) {
Util::Set delta_set(32, (unsigned char*)&delta); Util::Set delta_set(32, (unsigned char*)&delta);
for (int i = 0; i < 32; ++i) { for (int i = 0; i < 20; ++i) {
if (delta_set.get_item(i)) { if (delta_set.get_item(i)) {
assert(i < info.deltaCount); assert(i < info.deltaCount);
const DeltaInfo & di = info.delta[i]; const DeltaInfo & di = info.delta[i];
applyDelta(info, buffer, b_offset, di); applyDelta(info, buffer, b_offset, di);
} }
} }
assert(0); for (int i=20; i < 24; i++) {
if (delta_set.get_item(i)) {
const DeltaInfo & di = info.delta[i - 20 + 6];
applyDelta(info, buffer, b_offset, di, true);
}
}
for (int i=24; i < 28; i++) {
if (delta_set.get_item(i)) {
const DeltaInfo & di = info.delta[i - 24 + 11];
applyDelta(info, buffer, b_offset, di, true);
}
}
//assert(0);
} }
else { else {
// delta is only an index; one to big // delta is only an index; one to big
@ -1006,6 +1025,13 @@ namespace OpenGTA {
int Graphics8Bit::RGBPalette::loadFromFile(PHYSFS_file* fd) { int Graphics8Bit::RGBPalette::loadFromFile(PHYSFS_file* fd) {
PHYSFS_read(fd, static_cast<void*>(&data), 1, 256*3); PHYSFS_read(fd, static_cast<void*>(&data), 1, 256*3);
/*
int max_sum = 0;
for (int i = 1; i < 256; i+=3) {
int sum = int(data[i]) + int(data[i+1]) + int(data[i+2]);
if (sum > max_sum)
max_sum = sum;
}*/
return 0; return 0;
} }

View File

@ -21,6 +21,7 @@
* distribution. * * distribution. *
************************************************************************/ ************************************************************************/
#include <sstream> #include <sstream>
#include <cassert>
#include "m_exceptions.h" #include "m_exceptions.h"
#include "fx_sdt.h" #include "fx_sdt.h"

View File

@ -15,6 +15,14 @@
* GNU Make * GNU Make
[ http://www.gnu.org/software/make/ ] [ http://www.gnu.org/software/make/ ]
= Optional software =
* Lua
[ http://www.lua.org/ ]
* SDL_mixer
[ http://www.libsdl.org/projects/SDL_mixer/ ]
* SDL_sound
[ http://icculus.org/SDL_sound/ ]
= Compiling = = Compiling =
Only tested on GNU Linux using gcc & make; I assume that GL, SDL and Only tested on GNU Linux using gcc & make; I assume that GL, SDL and
@ -27,7 +35,7 @@ The other programs are/were used for development or debugging.
The distributed win32 binaries are created with a cross-compiler. The distributed win32 binaries are created with a cross-compiler.
The file doc/compiling.txt in the source code release contains The file doc/compiling.txt in the source code release contains
information on the build process. more information about the build process.
= Installing the data-files = = Installing the data-files =
@ -37,7 +45,7 @@ These programs expect to find the data in the current directory, either
directly in the file-system or in a ZIP file (named 'gtadata.zip'). directly in the file-system or in a ZIP file (named 'gtadata.zip').
You want the content of the original game directory GTADATA, but not You want the content of the original game directory GTADATA, but not
the directory itself. the directory itself.
See mods/using_mods.txt for a slightly longer description. See doc/using_mods.txt for a slightly longer description.
Needed: Needed:
*.FXT, *.FON, *.CMP *.FXT, *.FON, *.CMP
@ -52,13 +60,28 @@ MISSION.INI
AUDIO/*.RAW AUDIO/*.SDT (sound effects) AUDIO/*.RAW AUDIO/*.SDT (sound effects)
AUDIO/*.WAV (cutscene text; in legacy format) AUDIO/*.WAV (cutscene text; in legacy format)
You may also want to keep the music (even though it isn't used yet).
It is safe to assume that Ogg Vorbis [ http://vorbis.com/ ] will
be supported, so you can encode the music files.
= Running = = Running =
Note: Binary releases only contain the 'viewer' application; the other
programs should only be intersting for developers (read: compile
them yourself).
== gfxextract == == gfxextract ==
Export/Display textures and sprites; Export/Display textures and sprites;
run ./gfxextract -h (or without any parameters) for usage info. run ./gfxextract -h (or without any parameters) for usage info.
== spriteplayer ==
Sprite graphics browser; shows internal indices, can display
animations (ped walking, car delta anims).
run ./spriteplayer -h for usage information.
== viewer == == viewer ==
Brain-dead immediate-mode renderer of the city (now with objects); with Brain-dead immediate-mode renderer of the city (now with objects); with
@ -72,33 +95,14 @@ The optional param loads the respective city; default is 0:
1 - SANB.CMP 1 - SANB.CMP
2 - MIAMI.CMP 2 - MIAMI.CMP
flags are: There are several flags; see the compiled-in usage information.
-V show version and compile time switches -V show version and compile time switches
-h show usage -h show usage
( The compiled-in usage information is more recent than the
following. )
* screen dimensions (have to specify neither or both)
-w width
-h height
* log verbosity
-l level (0 default; everything, 1 warn + error, 2 only error)
Using "-l 1" will make it easier to see actual error messages; Using "-l 1" will make it easier to see actual error messages;
sometimes there is a lot of noise on 'info' level (0). sometimes there is a lot of noise on 'info' level (0).
* style-file
-c 0 (default; uses .GRY 8bit styles)
-c 1 (uses .G24 24bit styles)
* other map & graphics files (have to specify neither or both)
-m map_filename -g style_filename
This is for loading non-GTA1 data; like GTA London.
keys: keys:
ESC, cursor-keys, + and - do what you might except them to do; ESC, cursor-keys, + and - do what you might except them to do;
@ -108,7 +112,7 @@ furthermore:
. : decrease visible range . : decrease visible range
, : increase visible range , : increase visible range
t : display entire city (at a crawl) t : display entire city (at a crawl)
f : toggle fullscreen/windowed f : toggle fullscreen/windowed [only works on Linux]
PRINT : save 'screenshot.bmp' in current directory PRINT : save 'screenshot.bmp' in current directory
p : dump coords (in lua syntax) to stdout p : dump coords (in lua syntax) to stdout
F2 : toggle drawing of sprite bounding-boxes F2 : toggle drawing of sprite bounding-boxes
@ -118,6 +122,7 @@ furthermore:
F6 : city map mode (ESC to exit, +, -, cursor keys) F6 : city map mode (ESC to exit, +, -, cursor keys)
F9 : toggle city blocks drawn textured F9 : toggle city blocks drawn textured
F10 : toggle blocks wireframe lines F10 : toggle blocks wireframe lines
F12 : show/hide screen-gamma scrollbar
in 3d view: in 3d view:
w : forward w : forward
@ -132,11 +137,15 @@ to 3d and the screen is black: move the mouse down.
in follow-player mode: in follow-player mode:
i,j,k,l : move player-char i,j,k,l : move player-char
l-shift : toggle walking/running l-shift : toggle walking/running
l-ctrl : shoot
0 : unselect weapon / unarmed 0 : unselect weapon / unarmed
1,2,3,4 : select weapon (only switches graphic) 1,2,3,4 : select weapon (only switches graphic)
F7 : draw explosion at player pos (graphical effect) F7 : draw explosion at player pos (graphical effect)
F8 : create random-walker ped at player-pos F8 : create random-walker ped at player-pos
You can still use + and - to zoom; but the view will try
to return to the old position quickly.
== luaviewer: viewer + Lua (optional target) == == luaviewer: viewer + Lua (optional target) ==
Also needs Lua (only 5.1 tried) in path; run: 'make luaviewer' Also needs Lua (only 5.1 tried) in path; run: 'make luaviewer'

View File

@ -1,3 +1,5 @@
ogta/ai.cpp
ogta/ai.h
ogta/blockanim.cpp ogta/blockanim.cpp
ogta/blockanim.h ogta/blockanim.h
ogta/blockdata.cpp ogta/blockdata.cpp
@ -24,17 +26,22 @@ ogta/coldet/transform.txt
ogta/coldet/tritri.c ogta/coldet/tritri.c
ogta/common_sdl_gl.cpp ogta/common_sdl_gl.cpp
ogta/common_sdl_gl.h ogta/common_sdl_gl.h
ogta/cvs_changelog.txt
ogta/datahelper.cpp ogta/datahelper.cpp
ogta/datahelper.h ogta/datahelper.h
ogta/dataholder.cpp ogta/dataholder.cpp
ogta/dataholder.h ogta/dataholder.h
ogta/doc/compiling.txt
ogta/doc/doc_links.txt ogta/doc/doc_links.txt
ogta/doc/gouranga.txt ogta/doc/gouranga.txt
ogta/doc/gta1_winex.txt ogta/doc/gta1_winex.txt
ogta/doc/hacking.txt ogta/doc/hacking.txt
ogta/doc/more_hints_delfi.txt ogta/doc/more_hints_delfi.txt
ogta/doc/more_info.txt ogta/doc/more_info.txt
ogta/doc/ped_remaps.txt
ogta/doc/slopes1.txt ogta/doc/slopes1.txt
ogta/doc/sprites.txt
ogta/doc/using_mods.txt
ogta/Doxyfile ogta/Doxyfile
ogta/entity_controller.cpp ogta/entity_controller.cpp
ogta/entity_controller.h ogta/entity_controller.h
@ -70,6 +77,7 @@ ogta/licenses/readme.txt
ogta/licenses/zlib.txt ogta/licenses/zlib.txt
ogta/license.txt ogta/license.txt
ogta/lid_normal_data.h ogta/lid_normal_data.h
ogta/localplayer.cpp
ogta/localplayer.h ogta/localplayer.h
ogta/loki.make ogta/loki.make
ogta/loki.make.w32_cross ogta/loki.make.w32_cross
@ -80,6 +88,8 @@ ogta/lua_addon/lua_cityview.h
ogta/lua_addon/lua.hpp ogta/lua_addon/lua.hpp
ogta/lua_addon/lua_ini_bridge.cpp ogta/lua_addon/lua_ini_bridge.cpp
ogta/lua_addon/lua_ini_bridge.h ogta/lua_addon/lua_ini_bridge.h
ogta/lua_addon/lua_map.cpp
ogta/lua_addon/lua_map.h
ogta/lua_addon/lua_screen.cpp ogta/lua_addon/lua_screen.cpp
ogta/lua_addon/lua_screen.h ogta/lua_addon/lua_screen.h
ogta/lua_addon/lua_spritecache.cpp ogta/lua_addon/lua_spritecache.cpp
@ -101,6 +111,8 @@ ogta/math/obb.cpp
ogta/math/obb.hpp ogta/math/obb.hpp
ogta/math/obox.cpp ogta/math/obox.cpp
ogta/math/obox.h ogta/math/obox.h
ogta/math/plane.cpp
ogta/math/plane.h
ogta/math/quaternion.h ogta/math/quaternion.h
ogta/math/rectangle.hpp ogta/math/rectangle.hpp
ogta/math/vector.hpp ogta/math/vector.hpp
@ -136,6 +148,9 @@ ogta/release_files_sorted
ogta/scripts/demo1.lua ogta/scripts/demo1.lua
ogta/scripts/demo2.lua ogta/scripts/demo2.lua
ogta/scripts/demo3.lua ogta/scripts/demo3.lua
ogta/scripts/dump_config.lua
ogta/scripts/map_test_blocktype.lua
ogta/scripts/parser.lua
ogta/slope1_data.h ogta/slope1_data.h
ogta/slope1_tcoords.h ogta/slope1_tcoords.h
ogta/slope_height_func.cpp ogta/slope_height_func.cpp
@ -143,25 +158,39 @@ ogta/sprite_anim_player.cpp
ogta/spritemanager.cpp ogta/spritemanager.cpp
ogta/spritemanager.h ogta/spritemanager.h
ogta/tests/interpolate_test.cpp ogta/tests/interpolate_test.cpp
ogta/tests/lua_map_test.cpp
ogta/tests/menudemo.cpp ogta/tests/menudemo.cpp
ogta/tests/new_obj_test.cpp ogta/tests/new_obj_test.cpp
ogta/tests/plot_interpolate.sh
ogta/tests/rectangle.cpp
ogta/tests/sound_test1.cpp ogta/tests/sound_test1.cpp
ogta/tools/analyse_lids_2.c ogta/tools/analyse_lids_2.c
ogta/tools/analyse_lids.c ogta/tools/analyse_lids.c
ogta/tools/blockview.cpp ogta/tools/blockview.cpp
ogta/tools/bug_parser.awk
ogta/tools/build_svg_rect.sh
ogta/tools/car_dump.cpp
ogta/tools/create_normals.cpp ogta/tools/create_normals.cpp
ogta/tools/display_font.cpp ogta/tools/display_font.cpp
ogta/tools/display_slopes.cpp ogta/tools/display_slopes.cpp
ogta/tools/doxy_doc.sh ogta/tools/doxy_doc.sh
ogta/tools/fxt.c
ogta/tools/gen_texcoords.c ogta/tools/gen_texcoords.c
ogta/tools/insert_copyright.sh ogta/tools/insert_copyright.sh
ogta/tools/label_screenshot.sh
ogta/tools/mapinfo.cpp ogta/tools/mapinfo.cpp
ogta/tools/minimap.cpp ogta/tools/minimap.cpp
ogta/tools/obj_dump.cpp ogta/tools/obj_dump.cpp
ogta/tools/package_binary.sh
ogta/tools/picasa_ls.sh
ogta/tools/plot_stats.sh
ogta/tools/projects_stats.sh
ogta/tools/raw_images.m4
ogta/tools/replace_in_files.sh ogta/tools/replace_in_files.sh
ogta/tools/resort_quads.c ogta/tools/resort_quads.c
ogta/tools/slope_conv.awk ogta/tools/slope_conv.awk
ogta/tools/slope_exchange.sh ogta/tools/slope_exchange.sh
ogta/tools/stats_recalc.sh
ogta/tools/style_demo.sh ogta/tools/style_demo.sh
ogta/train_system.cpp ogta/train_system.cpp
ogta/train_system.h ogta/train_system.h
@ -175,15 +204,20 @@ ogta/util/cell_iterator.h
ogta/util/cistring.h ogta/util/cistring.h
ogta/util/file_helper.cpp ogta/util/file_helper.cpp
ogta/util/file_helper.h ogta/util/file_helper.h
ogta/util/gui.cpp
ogta/util/gui.h ogta/util/gui.h
ogta/util/image_loader.cpp ogta/util/image_loader.cpp
ogta/util/image_loader.h ogta/util/image_loader.h
ogta/util/key_handler.cpp
ogta/util/key_handler.h
ogta/util/log.cpp ogta/util/log.cpp
ogta/util/log.h ogta/util/log.h
ogta/util/map_helper.cpp ogta/util/map_helper.cpp
ogta/util/map_helper.h ogta/util/map_helper.h
ogta/util/m_exceptions.cpp ogta/util/m_exceptions.cpp
ogta/util/m_exceptions.h ogta/util/m_exceptions.h
ogta/util/pf_tree.cpp
ogta/util/pf_tree.hpp
ogta/util/physfsrwops.c ogta/util/physfsrwops.c
ogta/util/physfsrwops.h ogta/util/physfsrwops.h
ogta/util/sample_cache.h ogta/util/sample_cache.h

View File

@ -20,7 +20,7 @@ tick = 0
-- every 100 ms, but it is pretty pointless at this time. -- every 100 ms, but it is pretty pointless at this time.
function game_tick() function game_tick()
if tick == 1 then if tick == 1 then
screen.makeScreenShot("test.bmp") --screen.makeScreenShot("test.bmp")
end end
tick = tick + 1 tick = tick + 1
end end

View File

@ -1,4 +1,5 @@
screen.setFullscreen(true)
--screen.setFullscreen(true)
camera.setCenter(61.4261, 7.56265, 2.2242) camera.setCenter(61.4261, 7.56265, 2.2242)
camera.setEye(61.4185, 8.72266, 0.810034) camera.setEye(61.4185, 8.72266, 0.810034)
camera.setUp(0, 1, 0) camera.setUp(0, 1, 0)

40
scripts/dump_config.lua Normal file
View File

@ -0,0 +1,40 @@
function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end
function config_as_string()
local conf_str = ""
if type(config) ~= 'table' then return conf_str end
table.sort(config)
for i, j in pairsByKeys(config) do
if type(j) == 'boolean' then
if j == true then
conf_str = conf_str .. i .. ' = true\n'
else
conf_str = conf_str .. i .. ' = false\n'
end
elseif type(j) == 'string' then
conf_str = conf_str .. i .. ' = "' .. j .. '"\n'
else
conf_str = conf_str .. i .. ' = ' .. j .. '\n'
end
end
return conf_str
end
print("-- CONFIG DUMP --")
print(config_as_string())
print("-- END OF CONFIG --")
quit()

View File

@ -0,0 +1,97 @@
-- run it:
-- ./lua_map_test $map_file scripts/map_test_blocktype.lua
--
-- may soon also work from within luaviewer
if rawget(_G, 'map') == nil then
print("No map loaded!")
os.exit()
end
function block_type_name(t)
if t == 0 then return "air" end
if t == 1 then return "water" end
if t == 2 then return "road" end
if t == 3 then return "pavement" end
if t == 4 then return "field" end
if t == 5 then return "building" end
if t == 6 then return "unused1" end
if t == 7 then return "unused2" end
return "????????"
end
function find_all_of_type(t)
list = {}
for y = 0, 255 do
for x = 0, 255 do
c = map:getNumBlocksAt(x, y)
for i = 0, c - 1 do
info = map:getBlockAt(x, y, i)
if info:getBlockType() == t then
table.insert(list, { x, y, i })
end
end
end
end
return list
end
function find_air_columns()
for y = 0, 255 do
for x = 0, 255 do
c = map:getNumBlocksAt(x, y)
is_air = true
for i = 0, c - 1 do
info = map:getBlockAt(x, y, i)
if info:getBlockType() ~= 0 then
is_air = false
end
end
if is_air == true then
for i = 0, c - 1 do
info = map:getBlockAt(x, y, i)
lid = info:getTextureId(0)
if lid > 0 and i < 4 then
print("Air-column: " .. x .. ", " .. y)
print("Texture " .. lid .. " set at " .. i)
end
end
end
end
end
end
function is_block_of_type(x, y, z, t)
local c = map:getNumBlocksAt(x, y)
assert(c > z)
local info = map:getBlockAt(x, y, z)
return info:getBlockType() == t
end
--find_air_columns()
function find_block_holes()
for y = 0, 255 do
for x = 0, 255 do
c = map:getNumBlocksAt(x, y)
info = map:getBlockAt(x, y, c - 1)
if info:getTextureId(0) > 0 and info:getBlockType() == 0 then
print(x .. ", " .. y .. " has texture but no type above; level: " .. c - 1 ..
" lid: " .. info:getTextureId(0))
end
end
end
end
find_block_holes()
--num = map:getNumBlocksAt(25, 17)
--for i = 0, num-1 do
-- info = map:getBlockAt(25, 17, i)
-- info:setBlockType(3)
-- print(i)
-- print("texture: " .. info:getTextureId(0))
-- print("type: " .. info:getBlockType())
--end

122
scripts/parser.lua Normal file
View File

@ -0,0 +1,122 @@
local n
--definition_indices = {}
--for n in pairs(definitions) do table.insert(definition_indices, n) end
--table.sort(definition_indices)
command_indices = {}
for n in pairs(commands) do table.insert(command_indices, n) end
table.sort(command_indices)
function idx_by_gtaidx(gta_idx)
local i
for i = 1, #command_indices do
if command_indices[i] == gta_idx then return i end
end
--error("Invalid gta-cmd-idx: " .. gta_idx)
return -1
end
-- from: http://lua-users.org/wiki/StringRecipes
-- Compatibility: Lua-5.1
function split(str, pat)
local t = {} -- NOTE: use {n = 0} in Lua-5.0
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = string.find(str, fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = string.find(str, fpat, last_end)
end
if last_end <= string.len(str) then
cap = string.sub(str, last_end)
table.insert(t, cap)
end
return t
end
function run_command(idx, cmd, params)
local res = 0
if cmd == "KICKSTART" then
-- new_thread(idx, params[1])
print("\tKICKSTART in " .. idx .. " from " .. params[1] .. " = " ..idx_by_gtaidx(params[1] + 0))
new_thread(idx, idx_by_gtaidx(params[1] + 0))
else
print("\t" .. cmd .. " in line " .. idx)
end
return res
end
function iterate_commands(idx)
local is_sleeping = false
while idx <= #command_indices do
local gta_idx = command_indices[idx]
if is_sleeping == true then
while true do
print(" thread is sleeping in " .. gta_idx)
coroutine.yield()
end
end
--print("LINE " .. gta_idx)
local cmd = commands[gta_idx]
local cmd_split = split(cmd, " ")
local cmd_name = cmd_split[1]
--print(cmd)
table.remove(cmd_split, 1)
local ok_idx = cmd_split[2]
local fail_idx = cmd_split[3]
if idx == 1 then
idx = idx + 1
elseif idx > 1 then
local next_idx = 0
--print(" "..gta_idx .. " " .. cmd_name)
if run_command(gta_idx, cmd_name, cmd_split) == 1 then
next_idx = fail_idx + 0
print(' failed '..fail_idx)
else
next_idx = ok_idx + 0
print(' ok '..ok_idx)
end
if next_idx == 0 then
idx = idx + 1
elseif next_idx == -1 then
if cmd_name == "CRANE" then idx = idx + 1
else
is_sleeping = true
--error("EXIT: " .. next_idx)
end
else
idx = idx_by_gtaidx(next_idx)
end
end
coroutine.yield()
print(' RESUMING2')
end
coroutine.yield()
print(' RESUMING3')
end
threads = {}
thread_indices = {}
function new_thread(t_id, start_at_idx)
table.insert(threads, coroutine.create(function () iterate_commands(start_at_idx) end))
print(" "..#threads .. " = " ..t_id)
table.insert(thread_indices, t_id)
end
new_thread(0, 1)
while #threads > 0 do
for i, j in pairs(threads) do
print("thread " .. thread_indices[i] .. " [" .. #threads .. "]")
if coroutine.status(j) == "suspended" then
coroutine.resume(j)
elseif coroutine.status(j) == "dead" then
table.remove(threads, i)
table.remove(thread_indices, i)
print("removing dead " .. i)
end
end
end

View File

@ -1084,11 +1084,12 @@
{ 1.00, 1.00 } { 1.00, 1.00 }
}, },
{ // east { // east
{ 1.00, 0.00 }, { 0.00, 0.00 },
{ 0.00, 1.00 }, { 1.00, 1.00 },
{ 0.00, 1.00 }, { 1.00, 1.00 },
{ 1.00, 1.00 } { 0.00, 1.00 }
} }
}, },
{ // slope: 42 { // slope: 42
{ // north { // north
@ -1110,10 +1111,10 @@
{ 1.00, 1.00 } { 1.00, 1.00 }
}, },
{ // east { // east
{ 1.00, 1.00 },
{ 0.00, 0.00 }, { 0.00, 0.00 },
{ 0.00, 1.00 }, { 1.00, 0.00 },
{ 1.00, 1.00 } { 1.00, 1.00 },
{ 0.00, 1.00 }
} }
}, },
{ // slope: 43 { // slope: 43

View File

@ -36,7 +36,10 @@
extern int global_EC; extern int global_EC;
extern int global_Done; extern int global_Done;
std::string style_file("STYLE001.GRY"); std::string style_file("STYLE001.GRY");
float screen_gamma = 1.0f;
OpenGTA::Car * car = NULL;
Vector3D _p(4, 0.01f, 4);
OpenGTA::Pedestrian ped(Vector3D(0.5f, 0.5f, 0.5f), Vector3D(4, 0.01f, 4), 0xffffffff); OpenGTA::Pedestrian ped(Vector3D(0.5f, 0.5f, 0.5f), Vector3D(4, 0.01f, 4), 0xffffffff);
OpenGTA::SpriteObject::Animation pedAnim(0, 0); OpenGTA::SpriteObject::Animation pedAnim(0, 0);
@ -47,19 +50,43 @@ int first_offset = 0;
int second_offset = 0; int second_offset = 0;
int now_frame = 0; int now_frame = 0;
bool play_anim = false; bool play_anim = false;
unsigned int play_anim_time = 0;
int bbox_toggle = 0; int bbox_toggle = 0;
int texsprite_toggle = 0; int texsprite_toggle = 0;
int c_c = 1;
int car_model = 0;
int car_remap = -1;
int car_last_model_ok = 0;
bool playWithCar = false;
uint32_t car_delta = 0;
int spr_type = (int)ped.sprType; int spr_type = (int)ped.sprType;
namespace OpenGTA { namespace OpenGTA {
void ai_step_fake(OpenGTA::Pedestrian*) { void ai_step_fake(OpenGTA::Pedestrian*) {
} }
} }
void on_exit() { void on_exit() {
if (car)
delete car;
SDL_Quit(); SDL_Quit();
PHYSFS_deinit(); PHYSFS_deinit();
} }
void safe_try_model(uint8_t model_id) {
if (car)
delete car;
car = NULL;
try {
car = new OpenGTA::Car(_p, 0, 0, model_id, car_remap);
}
catch (Util::UnknownKey & uk) {
car = NULL;
ERROR << "not a model" << std::endl;
return;
}
car_last_model_ok = model_id;
}
void run_init(const char*) { void run_init(const char*) {
PHYSFS_init("mapview"); PHYSFS_init("mapview");
@ -69,9 +96,14 @@ void run_init(const char*) {
SDL_EnableKeyRepeat( 100, SDL_DEFAULT_REPEAT_INTERVAL ); SDL_EnableKeyRepeat( 100, SDL_DEFAULT_REPEAT_INTERVAL );
OpenGTA::StyleHolder::Instance().load(style_file); OpenGTA::StyleHolder::Instance().load(style_file);
OpenGTA::StyleHolder::Instance().get().setDeltaHandling(true);
OpenGTA::MainMsgHolder::Instance().load("ENGLISH.FXT");
m_font.loadFont("STREET1.FON"); m_font.loadFont("F_MTEXT.FON");
m_font.setScale(2); m_font.setScale(1);
glClearColor(1, 1, 1, 1);
if (playWithCar)
car = new OpenGTA::Car(_p, 0, 0, car_model);
} }
const char* spr_type_name(int t) { const char* spr_type_name(int t) {
@ -122,6 +154,20 @@ const char* spr_type_name(int t) {
return "???"; return "???";
} }
const char* vtype2name(int vt) {
switch(vt) {
case 0:
return "bus";
case 3:
return "motorcycle";
case 4:
return "car";
case 8:
return "train";
}
return "";
}
void drawScene(Uint32 ticks) { void drawScene(Uint32 ticks) {
GL_CHECKERROR; GL_CHECKERROR;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -129,8 +175,36 @@ void drawScene(Uint32 ticks) {
OpenGL::ScreenHolder::Instance().set3DProjection(); OpenGL::ScreenHolder::Instance().set3DProjection();
OpenGL::CameraHolder::Instance().update(ticks); OpenGL::CameraHolder::Instance().update(ticks);
if (play_anim) { if (playWithCar) {
pedAnim.firstFrameOffset = now_frame; if (car) {
car->update(ticks);
OpenGTA::SpriteManagerHolder::Instance().draw(*car);
}
OpenGL::ScreenHolder::Instance().setFlatProjection();
glPushMatrix();
glTranslatef(10, 10, 0);
std::ostringstream sprite_info_str;
std::ostringstream ostr;
ostr << "car" << int(car_model);
if (car) {
sprite_info_str << vtype2name(car->carInfo.vtype)<< " model: " << int(car_model) << " name: " <<
OpenGTA::MainMsgHolder::Instance().get().getText(ostr.str());
}
else
sprite_info_str << "not a model: " << int(car_model);
m_font.drawString(sprite_info_str.str());
glPopMatrix();
}
else {
if (play_anim && ticks > play_anim_time + 200) {
now_frame++;
if (now_frame > second_offset)
now_frame = first_offset;
ped.anim.firstFrameOffset = now_frame;
play_anim_time = ticks;
} }
OpenGTA::SpriteManagerHolder::Instance().draw(ped); OpenGTA::SpriteManagerHolder::Instance().draw(ped);
@ -142,6 +216,7 @@ void drawScene(Uint32 ticks) {
sprite_info_str << spr_type_name(spr_type) << " offset " << frame_offset; sprite_info_str << spr_type_name(spr_type) << " offset " << frame_offset;
m_font.drawString(sprite_info_str.str()); m_font.drawString(sprite_info_str.str());
glPopMatrix(); glPopMatrix();
}
SDL_GL_SwapBuffers(); SDL_GL_SwapBuffers();
GL_CHECKERROR; GL_CHECKERROR;
@ -155,25 +230,93 @@ void handleKeyPress( SDL_keysym *keysym ) {
case SDLK_ESCAPE: case SDLK_ESCAPE:
global_Done = 1; global_Done = 1;
break; break;
case SDLK_TAB:
c_c += 1; c_c %= 2;
glClearColor(c_c, c_c, c_c, 0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
break;
case 'k':
if (car_delta > 0)
car_delta -= 1;
if (car)
car->delta = car_delta;
break;
case 'l':
if (car_delta < 32)
car_delta += 1;
if (car) {
car->delta = car_delta;
}
break;
case '+': case '+':
cam.translateBy(Vector3D(0, -0.5f, 0)); cam.translateBy(Vector3D(0, -0.5f, 0));
break; break;
case '-': case '-':
cam.translateBy(Vector3D(0, 0.5f, 0)); cam.translateBy(Vector3D(0, 0.5f, 0));
break; break;
case '1':
if (playWithCar) {
if (car->animState.get_item(1))
car->closeDoor(0);
else
car->openDoor(0);
}
break;
case '2':
if (playWithCar) {
if (car->animState.get_item(2))
car->closeDoor(1);
else
car->openDoor(1);
}
break;
case '3':
if (playWithCar) {
if (car->animState.get_item(3))
car->closeDoor(2);
else
car->openDoor(2);
}
break;
case '4':
if (playWithCar) {
if (car->animState.get_item(4))
car->closeDoor(3);
else
car->openDoor(3);
}
break;
case ',': case ',':
if (playWithCar) {
car_model -= 1;
if (car_model < 0)
car_model = 0;
}
frame_offset -= 1; frame_offset -= 1;
if (frame_offset < 0) if (frame_offset < 0)
frame_offset = 0; frame_offset = 0;
update_anim = true; update_anim = true;
break; break;
case '.': case '.':
if (playWithCar) {
car_model += 1;
if (car_model > 88)
car_model = 88;
}
frame_offset += 1; frame_offset += 1;
if (frame_offset >= style.spriteNumbers.countByType(ped.sprType)) if (frame_offset >= style.spriteNumbers.countByType(ped.sprType))
frame_offset -= 1; frame_offset -= 1;
update_anim = true; update_anim = true;
break; break;
case 'n': case 'n':
if (playWithCar) {
car_remap -= 1;
if (car_remap < -1)
car_remap = -1;
INFO << "remap: " << int(car_remap) << std::endl;
}
do { do {
spr_type -= 1; spr_type -= 1;
if (spr_type < 0) if (spr_type < 0)
@ -185,6 +328,12 @@ void handleKeyPress( SDL_keysym *keysym ) {
update_anim = 1; update_anim = 1;
break; break;
case 'm': case 'm':
if (playWithCar) {
car_remap += 1;
if (car_remap > 11)
car_remap = 11;
INFO << "remap: " << int(car_remap) << std::endl;
}
do { do {
spr_type += 1; spr_type += 1;
if (spr_type > 20) if (spr_type > 20)
@ -195,6 +344,11 @@ void handleKeyPress( SDL_keysym *keysym ) {
frame_offset = 0; frame_offset = 0;
update_anim = 1; update_anim = 1;
break; break;
case 's':
if (playWithCar) {
car->setSirenAnim(true);
}
break;
case SDLK_F2: case SDLK_F2:
bbox_toggle = (bbox_toggle ? 0 : 1); bbox_toggle = (bbox_toggle ? 0 : 1);
OpenGTA::SpriteManagerHolder::Instance().setDrawBBox(bbox_toggle); OpenGTA::SpriteManagerHolder::Instance().setDrawBBox(bbox_toggle);
@ -205,9 +359,21 @@ void handleKeyPress( SDL_keysym *keysym ) {
break; break;
case SDLK_F5: case SDLK_F5:
first_offset = frame_offset; first_offset = frame_offset;
std::cout << "First frame: " << first_offset << std::endl;
break; break;
case SDLK_F6: case SDLK_F6:
second_offset = frame_offset; second_offset = frame_offset;
std::cout << "Last frame: " << second_offset << std::endl;
break;
case SDLK_F7:
play_anim = (play_anim ? false : true);
if (play_anim)
std::cout << "Playing: " << first_offset << " .. " << second_offset << std::endl;
now_frame = first_offset;
break;
case SDLK_F8:
playWithCar = playWithCar ? false : true;
update_anim = true;
break; break;
default: default:
break; break;
@ -215,6 +381,8 @@ void handleKeyPress( SDL_keysym *keysym ) {
if (update_anim) { if (update_anim) {
pedAnim.firstFrameOffset = frame_offset; pedAnim.firstFrameOffset = frame_offset;
ped.anim = pedAnim; ped.anim = pedAnim;
if (playWithCar)
safe_try_model(car_model);
} }
} }
@ -225,8 +393,18 @@ void usage(const char* a0) {
" + - : zoom in/out" << std::endl << " + - : zoom in/out" << std::endl <<
" , . : previous/next frame offset" << std::endl << " , . : previous/next frame offset" << std::endl <<
" n m : previous/next sprite-type" << std::endl << " n m : previous/next sprite-type" << std::endl <<
" tab : black/white background" << std::endl <<
" F2 : toggle BBox drawn" << std::endl << " F2 : toggle BBox drawn" << std::endl <<
" F3 : toggle tex-border drawn" << std::endl; " F3 : toggle tex-border drawn" << std::endl <<
" F5 : prepare animation: first-frame = current frame" << std::endl <<
" F6 : prepare animation: last-frame = current frame" << std::endl <<
" F7 : toggle: play frames" << std::endl <<
" F8 : toggle: special-car-mode" << std::endl << std::endl <<
"In car-mode:" << std::endl <<
" , . : choose model" << std::endl <<
" n m : choose remap" << std::endl <<
" 1, 2, 3, 4 : open car door (if exists)" << std::endl <<
" s : toggle siren anim (if exists)" << std::endl;
} }
void parse_args(int argc, char* argv[]) { void parse_args(int argc, char* argv[]) {
@ -274,7 +452,7 @@ void run_main() {
handleKeyPress(&event.key.keysym); handleKeyPress(&event.key.keysym);
break; break;
case SDL_KEYUP: case SDL_KEYUP:
// handleKeyUp(&event.key.keysym); // handleKeyUp(&event.key.keysym);
break; break;
case SDL_VIDEORESIZE: case SDL_VIDEORESIZE:
OpenGL::ScreenHolder::Instance().resize(event.resize.w, event.resize.h); OpenGL::ScreenHolder::Instance().resize(event.resize.w, event.resize.h);

View File

@ -131,6 +131,7 @@ namespace OpenGTA {
car.update(ticks); car.update(ticks);
num_cars++; num_cars++;
} }
num_obj = 0;
for (AbstractContainer<SpriteObject>::Storage_T_Iterator i = AbstractContainer<SpriteObject>::objs.begin(); for (AbstractContainer<SpriteObject>::Storage_T_Iterator i = AbstractContainer<SpriteObject>::objs.begin();
i != AbstractContainer<SpriteObject>::objs.end(); ++i) { i != AbstractContainer<SpriteObject>::objs.end(); ++i) {
SpriteObject & obj = (*i); SpriteObject & obj = (*i);
@ -152,11 +153,13 @@ namespace OpenGTA {
} }
removeDeadStuff(); removeDeadStuff();
if (num_peds < 10 && num_peds > 0) { if (num_peds < 50 && num_peds > 2 && ticks - lastCreateTick > 100) {
//MapHelper::createPeds(5); //MapHelper::createPeds(5);
Map & map = OpenGTA::MapHolder::Instance().get(); Map & map = OpenGTA::MapHolder::Instance().get();
lastCreateTick = ticks;
while (1) { while (1) {
Util::TupleOfUint8 tu8 = creationArea.getValidCoord(); Util::TupleOfUint8 tu8 = creationArea.getValidCoord();
INFO << "testing: " << int(tu8.first) << ", " << int(tu8.second) << std::endl;
int k = -1; int k = -1;
for (int i = 0; i < map.getNumBlocksAtNew(tu8.first, tu8.second); ++i) { for (int i = 0; i < map.getNumBlocksAtNew(tu8.first, tu8.second); ++i) {
Map::BlockInfo * bi = map.getBlockAtNew(tu8.first, tu8.second, i); Map::BlockInfo * bi = map.getBlockAtNew(tu8.first, tu8.second, i);
@ -174,32 +177,41 @@ namespace OpenGTA {
int id = OpenGTA::TypeIdBlackBox::requestId(); int id = OpenGTA::TypeIdBlackBox::requestId();
Sint16 remap = OpenGTA::StyleHolder::Instance().get().getRandomPedRemapNumber(); Sint16 remap = OpenGTA::StyleHolder::Instance().get().getRandomPedRemapNumber();
OpenGTA::Pedestrian p(Vector3D(0.3f, 0.5f, 0.3f), pos, id, remap); OpenGTA::Pedestrian p(Vector3D(0.3f, 0.5f, 0.3f), pos, id, remap);
p.rot = 360 * (rand() / (RAND_MAX + 1.0));
OpenGTA::SpriteManagerHolder::Instance().add<Pedestrian>(p); OpenGTA::SpriteManagerHolder::Instance().add<Pedestrian>(p);
break; break;
} }
} }
} }
#define POS_INSIDE_RECT(pos, r) ((pos.x >= r.x) && \
(pos.x <= r.x + r.w) && (pos.z >= r.y) && (pos.z <= r.y + r.h))
void SpriteManager::drawInRect(SDL_Rect & r) { void SpriteManager::drawInRect(SDL_Rect & r) {
for (AbstractContainer<Pedestrian>::Storage_T_Iterator i = AbstractContainer<Pedestrian>::objs.begin(); for (AbstractContainer<Pedestrian>::Storage_T_Iterator i = AbstractContainer<Pedestrian>::objs.begin();
i != AbstractContainer<Pedestrian>::objs.end(); ++i) { i != AbstractContainer<Pedestrian>::objs.end(); ++i) {
Pedestrian & ped = (*i); Pedestrian & ped = (*i);
if ((ped.pos.x >= r.x) && (ped.pos.x <= r.x + r.w) && if (POS_INSIDE_RECT(ped.pos, r))
(ped.pos.z >= r.y) && (ped.pos.z <= r.y + r.h)) //if ((ped.pos.x >= r.x) && (ped.pos.x <= r.x + r.w) &&
// (ped.pos.z >= r.y) && (ped.pos.z <= r.y + r.h))
draw(ped); draw(ped);
else
removePed(ped.id());
} }
for (AbstractContainer<SpriteObject>::Storage_T_Iterator i = AbstractContainer<SpriteObject>::objs.begin(); for (AbstractContainer<SpriteObject>::Storage_T_Iterator i = AbstractContainer<SpriteObject>::objs.begin();
i != AbstractContainer<SpriteObject>::objs.end(); ++i) { i != AbstractContainer<SpriteObject>::objs.end(); ++i) {
SpriteObject & obj = (*i); SpriteObject & obj = (*i);
if ((obj.pos.x >= r.x) && (obj.pos.x <= r.x + r.w) && //if ((obj.pos.x >= r.x) && (obj.pos.x <= r.x + r.w) &&
(obj.pos.z >= r.y) && (obj.pos.z <= r.y + r.h)) // (obj.pos.z >= r.y) && (obj.pos.z <= r.y + r.h))
if (POS_INSIDE_RECT(obj.pos, r))
draw(obj); draw(obj);
} }
for (AbstractContainer<Car>::Storage_T_Iterator i = AbstractContainer<Car>::objs.begin(); for (AbstractContainer<Car>::Storage_T_Iterator i = AbstractContainer<Car>::objs.begin();
i != AbstractContainer<Car>::objs.end(); ++i) { i != AbstractContainer<Car>::objs.end(); ++i) {
Car & car = (*i); Car & car = (*i);
if ((car.pos.x >= r.x) && (car.pos.x <= r.x + r.w) && // if ((car.pos.x >= r.x) && (car.pos.x <= r.x + r.w) &&
(car.pos.z >= r.y) && (car.pos.z <= r.y + r.h)) // (car.pos.z >= r.y) && (car.pos.z <= r.y + r.h))
if (POS_INSIDE_RECT(car.pos, r))
draw(car); draw(car);
} }
@ -207,8 +219,7 @@ namespace OpenGTA {
typedef ProjectileListType::iterator ProjectileIterator; typedef ProjectileListType::iterator ProjectileIterator;
for (ProjectileIterator i = activeProjectiles.begin(); i != activeProjectiles.end(); ++i) { for (ProjectileIterator i = activeProjectiles.begin(); i != activeProjectiles.end(); ++i) {
Projectile & prj = (*i); Projectile & prj = (*i);
if ((prj.pos.x >= r.x) && (prj.pos.x <= r.x + r.w) && if (POS_INSIDE_RECT(prj.pos, r))
(prj.pos.z >= r.y) && (prj.pos.z <= r.y + r.h))
draw(prj); draw(prj);
} }
glColor3f(1, 1, 1); glColor3f(1, 1, 1);
@ -230,13 +241,13 @@ namespace OpenGTA {
} }
#define GL_OBJ_COMMON(o) GL_CHECKERROR; \ #define GL_OBJ_COMMON(o) GL_CHECKERROR; \
glPushMatrix(); \ glPushMatrix(); \
glTranslatef(o.pos.x, o.pos.y, o.pos.z); \ glTranslatef(o.pos.x, o.pos.y, o.pos.z); \
glRotatef(o.rot, 0, 1, 0); \ glRotatef(o.rot, 0, 1, 0); \
//glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)o.m_M.m) //glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)o.m_M.m)
#define DRAW_TEX_QUADS_OBJ(t, w, h) glBindTexture(GL_TEXTURE_2D, t.inPage); \ #define DRAW_TEX_QUADS_OBJ(t, w, h) glBindTexture(GL_TEXTURE_2D, t.inPage); \
glBegin(GL_QUADS); \ glBegin(GL_QUADS); \
glTexCoord2f(t.coords[0].u, t.coords[1].v); \ glTexCoord2f(t.coords[0].u, t.coords[1].v); \
glVertex3f(-w/2, 0.0f, h/2); \ glVertex3f(-w/2, 0.0f, h/2); \
glTexCoord2f(t.coords[1].u, t.coords[1].v); \ glTexCoord2f(t.coords[1].u, t.coords[1].v); \
@ -252,23 +263,30 @@ void SpriteManager::draw(Car & car) {
GL_OBJ_COMMON(car); GL_OBJ_COMMON(car);
GraphicsBase & style = StyleHolder::Instance().get(); GraphicsBase & style = StyleHolder::Instance().get();
OpenGL::PagedTexture t; OpenGL::PagedTexture t;
PHYSFS_uint16 sprNum = style.spriteNumbers.reIndex(car.sprNum + PHYSFS_uint16 sprNum = style.spriteNumbers.reIndex(car.sprNum, car.sprType);
car.anim.firstFrameOffset + car.anim.currentFrame, car.sprType); //+ car.anim.firstFrameOffset + car.anim.currentFrame, car.sprType);
GraphicsBase::SpriteInfo * info = style.getSprite(sprNum); GraphicsBase::SpriteInfo * info = style.getSprite(sprNum);
assert(info); assert(info);
float w = float(info->w) / 64.0f; float w = float(info->w) / 64.0f;
float h = float(info->h) / 64.0f; float h = float(info->h) / 64.0f;
if (OpenGL::SpriteCacheHolder::Instance().has(sprNum, car.remap)) OpenGL::SpriteIdentifier si(sprNum, car.remap, car.delta);
t = OpenGL::SpriteCacheHolder::Instance().get(sprNum, car.remap); if (OpenGL::SpriteCacheHolder::Instance().has(si))
t = OpenGL::SpriteCacheHolder::Instance().get(si);
else { else {
t = OpenGL::SpriteCacheHolder::Instance().create(car.sprNum + t = OpenGL::SpriteCacheHolder::Instance().create(car.sprNum,// +
car.anim.firstFrameOffset + car.anim.currentFrame, //car.anim.firstFrameOffset + car.anim.currentFrame,
car.sprType, car.remap); car.sprType, car.remap, car.delta);
} }
DRAW_TEX_QUADS_OBJ(t, w, h); DRAW_TEX_QUADS_OBJ(t, w, h);
glDisable(GL_TEXTURE_2D);
glBegin(GL_POINTS);
glVertex3f(car.carInfo.door[0].rpx / 64.0f, 0.1f, car.carInfo.door[0].rpy / 64.0f);
glEnd();
glEnable(GL_TEXTURE_2D);
if (getDrawBBox() || getDrawTexBorder()) if (getDrawBBox() || getDrawTexBorder())
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
@ -305,8 +323,8 @@ void SpriteManager::drawTextureOutline(const float & w, const float & h) {
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
glColor3f(float(202)/255.0f, float(31)/255.0f, float(123)/255.0f); glColor3f(float(202)/255.0f, float(31)/255.0f, float(123)/255.0f);
glVertex3f(-w/2, 0.0f, h/2); glVertex3f(-w/2, 0.0f, h/2);
glVertex3f(w/2, 0.0f, h/2); glVertex3f( w/2, 0.0f, h/2);
glVertex3f(w/2, 0.0f, -h/2); glVertex3f( w/2, 0.0f, -h/2);
glVertex3f(-w/2, 0.0f, -h/2); glVertex3f(-w/2, 0.0f, -h/2);
glVertex3f(-w/2, 0.0f, h/2); glVertex3f(-w/2, 0.0f, h/2);
glEnd(); glEnd();
@ -520,7 +538,7 @@ void SpriteManager::drawExplosion(SpriteObject & obj) {
} }
/* /*
void SpriteManager::draw(TrainSegment & train) { void SpriteManager::draw(TrainSegment & train) {
GL_OBJ_COMMON(train); GL_OBJ_COMMON(train);
GraphicsBase & style = StyleHolder::Instance().get(); GraphicsBase & style = StyleHolder::Instance().get();
@ -555,8 +573,8 @@ void SpriteManager::draw(TrainSegment & train) {
glPopMatrix(); glPopMatrix();
GL_CHECKERROR; GL_CHECKERROR;
} }
*/ */
void SpriteManager::draw(Projectile & proj) { void SpriteManager::draw(Projectile & proj) {
//GL_OBJ_COMMON(proj); // can't use; not derived from OBox //GL_OBJ_COMMON(proj); // can't use; not derived from OBox
@ -582,92 +600,21 @@ void SpriteManager::draw(Projectile & proj) {
GL_CHECKERROR; GL_CHECKERROR;
} }
/*
void SpriteManager::addPed(Pedestrian & ped) {
activePeds.push_back(ped);
}
Pedestrian & SpriteManager::getPedById(const Uint32 & id) {
PedListType::iterator i = activePeds.begin();
while (i != activePeds.end()) {
if (i->pedId == id)
return *i;
++i;
}
assert(0);
return *activePeds.begin();
}
TrainSegment & SpriteManager::getTrainById(const Uint32 & id) {
TrainListType::iterator i = activeTrains.begin();
while (i != activeTrains.end()) {
if (i->trainId == id)
return *i;
++i;
}
assert(0);
return *activeTrains.begin();
}
void SpriteManager::removePedById(const Uint32 & id) {
PedListType::iterator i = activePeds.begin();
while (i != activePeds.end()) {
if (i->pedId == id) {
activePeds.erase(i);
return;
}
++i;
}
WARN << "didn't find ped id " << id << " -- cannot remove"<<std::endl;
}
void SpriteManager::addCar(Car & car) {
activeCars.push_back(car);
}
Car & SpriteManager::getCarById(const Uint32 & id) {
CarListType::iterator i = activeCars.begin();
while (i != activeCars.end()) {
if (i->carId == id) {
return *i;
}
++i;
}
assert(0);
return *activeCars.begin();
}
void SpriteManager::addObject(GameObject & go) {
activeObjects.push_back(go);
}
void SpriteManager::createExplosion(Vector3D center) {
GameObject exp(center, 0, GraphicsBase::SpriteNumbers::EX);
exp.anim = SpriteObject::Animation(getAnimationById(99));
exp.anim.set(Util::Animation::PLAY_FORWARD, Util::Animation::LOOP);
INFO << exp.anim.currentFrame << " " << exp.anim.numFrames << " " << exp.anim.delay << std::endl;
activeObjects.push_back(exp);
}
GameObject & SpriteManager::getObjectById(const Uint32 & id) {
ObjectListType::iterator i = activeObjects.begin();
while (i != activeObjects.end()) {
if (i->objId == id) {
return *i;
}
++i;
}
assert(0);
return *activeObjects.begin();
}
*/
void SpriteManager::removeDeadStuff() { void SpriteManager::removeDeadStuff() {
AbstractContainer<Pedestrian>::doRealRemove(); AbstractContainer<Pedestrian>::doRealRemove();
AbstractContainer<Car>::doRealRemove(); AbstractContainer<Car>::doRealRemove();
AbstractContainer<SpriteObject>::doRealRemove(); AbstractContainer<SpriteObject>::doRealRemove();
AbstractContainer<Pedestrian>::Storage_T_Iterator i = AbstractContainer<Pedestrian>::objs.begin();
while (i != AbstractContainer<Pedestrian>::objs.end()) {
Pedestrian & ped = (*i);
if ((ped.isDead == 3) && (creationArea.isOnScreen(ped.pos) == false)) {
AbstractContainer<Pedestrian>::Storage_T_Iterator j = i; j++;
AbstractContainer<Pedestrian>::objs.erase(i);
i = j;
}
else
i++;
}
} }
SpriteObject::Animation & SpriteManager::getAnimationById(const Uint32 & id) { SpriteObject::Animation & SpriteManager::getAnimationById(const Uint32 & id) {

View File

@ -179,6 +179,7 @@ namespace OpenGTA {
private: private:
Uint32 drawMode; Uint32 drawMode;
Uint32 lastCreateTick;
//SpriteManager(const SpriteManager & o) : trainSystem(AbstractContainer<TrainSegment>::objs) {assert(0);} //SpriteManager(const SpriteManager & o) : trainSystem(AbstractContainer<TrainSegment>::objs) {assert(0);}
SpriteManager(const SpriteManager & o) {assert(0);} SpriteManager(const SpriteManager & o) {assert(0);}

49
tests/lua_map_test.cpp Normal file
View File

@ -0,0 +1,49 @@
#include <string>
#include "lua_vm.h"
#include "opengta.h"
#include "dataholder.h"
#include "file_helper.h"
#include "log.h"
std::string map_filename;
const char* script_file;
void on_exit() {
SDL_Quit();
PHYSFS_deinit();
}
void parse_args(int argc, char* argv[]) {
if (argc != 3) {
ERROR << "invalid args" << std::endl;
exit(1);
}
map_filename = std::string(argv[1]);
script_file = argv[2];
}
void run_init(const char* prg_name) {
PHYSFS_init(prg_name);
Util::FileHelper & fh = GET_FILE_HELPER;
if (fh.existsInSystemFS(fh.getBaseDataPath())) {
PHYSFS_addToSearchPath(GET_FILE_HELPER.getBaseDataPath().c_str(), 1);
}
else {
WARN << "Could not load data-source: " << fh.getBaseDataPath() << std::endl;
}
PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1);
}
void run_main() {
OpenGTA::Script::LuaVM & vm = OpenGTA::Script::LuaVMHolder::Instance();
OpenGTA::MainMsgHolder::Instance().load("ENGLISH.FXT");
OpenGTA::MapHolder::Instance().load(map_filename);
OpenGTA::Map & loadedMap = OpenGTA::MapHolder::Instance().get();
vm.setMap(loadedMap);
vm.runFile(script_file);
}

43
tests/plot_interpolate.sh Normal file
View File

@ -0,0 +1,43 @@
#!/bin/bash
function input_data() {
cat <<EOF
0
1
2
1
0
-1
-2
-1
0
1
2
1
0
-1
-2
-1
0
EOF
}
function transform() {
switch=$1
input_data | ./interpolate_test --$switch >gnuplot_data.$$
cat <<EOF >gnuplot_script.$$
plot "gnuplot_data.$$" title "$switch"
EOF
gnuplot gnuplot_script.$$ -
}
if [ ! -f interpolate_test ]; then
g++ -I ../math -o interpolate_test interpolate_test.cpp
fi
transform linear
transform cubic
transform cosine
transform hermite
rm -f gnuplot_data.$$ gnuplot_script.$$

75
tests/rectangle.cpp Normal file
View File

@ -0,0 +1,75 @@
#include <iostream>
#include "rectangle.hpp"
using namespace std;
using namespace Math;
template <typename T> bool test_values ( const Rectangle<T> & r, T x, T y, T w, T h ) {
return (r.x == x && r.y == y && r.w == w && r.h == h);
}
int main(int argc, char* argv[]) {
/*
#define TEST_SET_1 5, 10, 24, 31
Rectangle<int> a(TEST_SET_1);
if (!test_values<int>(a, TEST_SET_1))
cerr << "verifying values failed " << __LINE__ << endl;
Rectangle<int> a_copy(a);
if (!test_values<int>(a_copy, TEST_SET_1))
cerr << "copy-constructor failed " << __LINE__ << endl;
if (! (a == a_copy) )
cerr << "equality failed " << __LINE__ << endl;
if (! a.isInside(15, 15) )
cerr << "isInside failed " << __LINE__ << endl;
Rectangle<int> b(10, 15, 10, 15);
if (a == b )
cerr << "equality failed " << __LINE__ << endl;
if (! rectangle_test_inside<int>(a, b) )
cerr << "rect-inside-rect test failed " << __LINE__ << endl;
if (rectangle_test_leftborder<int>(a, b))
cerr << "rectangle-left-b failed " << __LINE__ << endl;
if (rectangle_test_rightborder<int>(a, b))
cerr << "rectangle-right-b failed " << __LINE__ << endl;
if (rectangle_test_topborder<int>(a, b))
cerr << "rectangle-top-b failed " << __LINE__ << endl;
if (rectangle_test_bottomborder<int>(a, b))
cerr << "rectangle-bottom-b failed " << __LINE__ << endl;
*/
typedef Rectangle<int> IRect;
int input[4];
for (int j = 0; j < 4; ++j) {
input[j] = 0;
input[j] = atoi(argv[j+1]);
}
IRect big(input[0], input[1], input[2], input[3]);
for (int j = 0; j < 4; ++j) {
input[j] = 0;
input[j] = atoi(argv[j+5]);
}
IRect small(input[0], input[1], input[2], input[3]);
list< IRect > mlist;
RectangleGeometry<int>::difference(mlist, big, small);
cout << mlist.size() << " rects returned" << endl;
list< IRect >::iterator i;
for (i = mlist.begin(); i != mlist.end(); ++i) {
cout << "x = " << i->x << " y = " << i->y
<< " w = " << i->w << " h = " << i->h << endl;
}
}

View File

@ -1,62 +1,38 @@
#include <iostream> #include <iostream>
#include <SDL_opengl.h> #include <SDL_opengl.h>
#include "common_sdl_gl.h"
#include "opengta.h" #include "opengta.h"
#include "gl_texturecache.h" #include "dataholder.h"
#include "gl_screen.h"
#include "gl_camera.h"
#include "log.h"
namespace OpenGTA { Uint32 arg_screen_w = 0;
class MapViewGL { Uint32 arg_screen_h = 0;
private: std::string map_file("NYC.CMP");
Map* currentMap; Vector3D e(3, 3, 3);
Graphics8Bit* styleDB; Vector3D c(0.5f, 0.5f, 0.5f);
OpenGL::TextureCache<uint8_t>* sideCache; Vector3D u(0, 1, 0);
OpenGL::TextureCache<uint8_t>* lidCache; uint8_t which = 0;
public: float r = 0;
MapViewGL(); bool wireframe = true;
~MapViewGL();
int loadMap(const std::string &map, const std::string &style);
void drawMap(int32_t x, int32_t y, int32_t dx, int32_t dy);
void drawBlock(Map::BlockInfo* bi);
};
}
namespace OpenGTA {
MapViewGL::MapViewGL() {
currentMap = NULL;
styleDB = NULL;
sideCache = NULL;
lidCache = NULL;
}
MapViewGL::~MapViewGL() {
if (currentMap)
delete currentMap;
if (styleDB)
delete styleDB;
if (sideCache)
delete sideCache;
if (lidCache)
delete lidCache;
}
int MapViewGL::loadMap(const std::string &map, const std::string &style) {
currentMap = new Map(map);
styleDB = new Graphics8Bit(style);
sideCache = new OpenGL::TextureCache<uint8_t>();
lidCache = new OpenGL::TextureCache<uint8_t>();
//currentMap->dump();
return 0;
}
}
extern SDL_Surface* screen;
GLfloat mapPos[3] = {12.0f, 12.0f, 20.0f};
GLfloat camVec[3] = {0.0f, 1.0f, 0.0f};
OpenGTA::MapViewGL *map = NULL; extern int global_EC;
extern int global_Done;
const size_t numBlockTypes = 53;
const size_t numFaces = 5;
float slope_raw_data[numBlockTypes][numFaces][4][3] = {
#include "slope2_data.h"
};
#define SLOPE_RAW_DATA slope_raw_data
void on_exit() { void on_exit() {
SDL_FreeSurface(screen);
SDL_Quit(); SDL_Quit();
if (map)
delete map;
PHYSFS_deinit(); PHYSFS_deinit();
if (global_EC) if (global_EC)
std::cerr << "Exiting after fatal problem - please see output above" << std::endl; std::cerr << "Exiting after fatal problem - please see output above" << std::endl;
@ -64,254 +40,170 @@ void on_exit() {
std::cout << "Goodbye" << std::endl; std::cout << "Goodbye" << std::endl;
} }
void print_usage(const char*) {
}
void parse_args(int argc, char* argv[]) {
}
void handleKeyPress( SDL_keysym *keysym ) { void handleKeyPress( SDL_keysym *keysym ) {
switch ( keysym->sym ) { switch ( keysym->sym ) {
case SDLK_ESCAPE: case SDLK_ESCAPE:
global_Done = 1; global_Done = 1;
break; break;
case SDLK_LEFT: case SDLK_LEFT:
mapPos[0] += 1.0f; r -= 10;
break; break;
case SDLK_RIGHT: case SDLK_RIGHT:
mapPos[0] -= 1.0f; r += 10;
if (mapPos[0] < 0.0f) break;
mapPos[0] = 0.0f; case SDLK_SPACE:
wireframe = (wireframe) ? false : true;
break; break;
case SDLK_UP: case SDLK_UP:
mapPos[1] += 1.0f; which++;
if (which >= numBlockTypes)
which = numBlockTypes - 1;
INFO << "slope-type: " << int(which) << std::endl;
break; break;
case SDLK_DOWN: case SDLK_DOWN:
mapPos[1] -= 1.0f; if (which > 0)
if (mapPos[1] < 0.0f) which--;
mapPos[1] = 0.0f; INFO << "slope-type: " << int(which) << std::endl;
break;
case '+':
mapPos[2] += 1.0f;
break;
case '-':
mapPos[2] -= 1.0f;
break;
case 'x':
camVec[0] = 1.0f; camVec[1] = 0.0f; camVec[2] = 0.0f;
break;
case 'y':
camVec[0] = 0.0f; camVec[1] = 1.0f; camVec[2] = 0.0f;
break;
case 'z':
camVec[0] = 0.0f; camVec[1] = 0.0f; camVec[2] = 1.0f;
break; break;
default: default:
break; break;
} }
} }
GLuint createGLTexture(GLsizei w, GLsizei h, const void* pixels) {
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, param);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, param);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// GL_LINEAR_MIPMAP_LINEAR);
/*gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, w,
h, GL_RGB, GL_UNSIGNED_BYTE, pixels);
*/
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
return tex;
}
void OpenGTA::MapViewGL::drawBlock(OpenGTA::Map::BlockInfo* bi) {
float size = 0.5f;
int jj = 0;
if (bi == NULL)
return;
glEnable(GL_TEXTURE_2D);
if (bi->left) {
// Left Face
if (!sideCache->hasTexture(bi->left)) {
styleDB->getSide(static_cast<unsigned int>(bi->left-1), 0, true);
sideCache->addTexture(bi->left, createGLTexture(64, 64, &styleDB->tileTmpRGBA));
}
glBindTexture(GL_TEXTURE_2D, sideCache->getTextureWithId(bi->left));
//}
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
//glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-size, -size, -size);// Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-size, -size, size);// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-size, size, size);// Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-size, size, -size);// Top Left Of The Texture and Quad
glEnd();
}
if (bi->right) {
// Right face
if (!sideCache->hasTexture(bi->right)) {
styleDB->getSide(static_cast<unsigned int>(bi->right-1), 0, true);
sideCache->addTexture(bi->right, createGLTexture(64, 64, &styleDB->tileTmpRGBA));
}
glBindTexture(GL_TEXTURE_2D, sideCache->getTextureWithId(bi->right));
//}
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f);
//glNormal3f(1.0f, 0.0f, 0.0f);
glVertex3f( size, -size, -size);// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f);
glVertex3f( size, size, -size);// Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f);
glVertex3f( size, size, size);// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f);
glVertex3f( size, -size, size);// Bottom Left Of The Texture and Quad
glEnd();
}
if (bi->top) {
// Back Face
if (!sideCache->hasTexture(bi->top)) {
styleDB->getSide(static_cast<unsigned int>(bi->top-1), 0, true);
sideCache->addTexture(bi->top, createGLTexture(64, 64, &styleDB->tileTmpRGBA));
}
glBindTexture(GL_TEXTURE_2D, sideCache->getTextureWithId(bi->top));
//}
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f);
//glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3f(-size, size, -size);// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-size, size, size);// Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f);
glVertex3f( size, size, size);// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f);
glVertex3f( size, size, -size);// Top Right Of The Texture and Quad
glEnd();
}
if (bi->bottom) {
// Front Face
if (!sideCache->hasTexture(bi->bottom)) {
styleDB->getSide(static_cast<unsigned int>(bi->bottom-1), 0, true);
sideCache->addTexture(bi->bottom, createGLTexture(64, 64, &styleDB->tileTmpRGBA));
}
glBindTexture(GL_TEXTURE_2D, sideCache->getTextureWithId(bi->bottom));
//}
glBegin(GL_QUADS);
//glNormal3f(0.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-size, -size, -size);// Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f);
glVertex3f( size, -size, -size);// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f);
glVertex3f( size, -size, size);// Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-size, -size, size);// Bottom Right Of The Texture and Quad
glEnd();
}
if (bi->lid) {
// Top Face
if (!lidCache->hasTexture(bi->lid)) {
styleDB->getLid(static_cast<unsigned int>(bi->lid-1), 0, true);
lidCache->addTexture(bi->lid, createGLTexture(64, 64, &styleDB->tileTmpRGBA));
}
if (bi->typeMapExt & 128) {
//std::cout << "blending!" << std::endl;
}
jj = 0;
if (bi->typeMap & 16384) {
jj += 2;
}
if (bi->typeMap & 32768) {
jj += 4;
}
GLfloat lidTex[8] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
#ifdef GLTEX_HELPER
#undef GLTEX_HELPER
#endif
#define GLTEX_HELPER \
glTexCoord2f(lidTex[jj], lidTex[jj+1]); jj += 2; if (jj > 6) { jj = 0; }
glBindTexture(GL_TEXTURE_2D, lidCache->getTextureWithId(bi->lid));
//}
glBegin(GL_QUADS);
GLTEX_HELPER;
//glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(-size, -size, size);// Bottom Left Of The Texture and Quad
GLTEX_HELPER;
glVertex3f( size, -size, size);// Bottom Right Of The Texture and Quad
GLTEX_HELPER;
glVertex3f( size, size, size);// Top Right Of The Texture and Quad
GLTEX_HELPER;
glVertex3f(-size, size, size);// Top Left Of The Texture and Quad
glEnd();
#undef GLTEX_HELPER
}
}
void OpenGTA::MapViewGL::drawMap(int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
if (x1 < 0)
x1 = 0;
if (y1 < 0)
y1 = 0;
// FIXME: can't access 255 either x or y... WHY?
if (x2 >= 255)
x2 = 255;
if (y2 >= 255)
y2 = 255;
//std::cout << "draw: " << x1 << " " << y1 << " - " << x2 << " " << y2 << std::endl;
sideCache->sink();
lidCache->sink();
for (int i = y1; i <= y2; i++) {
glPushMatrix();
glTranslatef(0.0f, -1.0f*i, 0.0f);
for (int j= x1; j <= x2; j++) {
glPushMatrix();
glTranslatef(1.0f*j, 0.0f, 0.0f);
PHYSFS_uint16 emptycount = currentMap->getNumBlocksAt(j,i);
/*glPushMatrix();
* for(int c=0; c < 6 - emptycount-1; c++) */
for (int c=6-emptycount-0; c >= 1; c--) {
drawBlock(currentMap->getBlockAt(j,i, c));
glTranslatef(0.0f, 0.0f, 1.0f);
}
glPopMatrix();
}
glPopMatrix();
}
sideCache->clear();
lidCache->clear();
}
void drawScene() { void drawScene() {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); OpenGL::ScreenHolder::Instance().set3DProjection();
gluLookAt(mapPos[0], -mapPos[1], mapPos[2], mapPos[0], -mapPos[1], 0.0f, camVec[0], camVec[1], camVec[2]); OpenGL::CameraHolder::Instance().update(1);
//map->drawMap(int(mapPos[0]), int(mapPos[1]));
map->drawMap(int32_t(mapPos[0])-10, int32_t(mapPos[1])-10,int32_t(mapPos[0])+10, int32_t(mapPos[1])+10); glRotatef(r, 0, 1, 0);
glColor3f(0.5f, 1, 0.2f);
// lid
if (wireframe)
glBegin(GL_LINE_STRIP);
else
glBegin(GL_QUADS);
for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][0][j][0],
SLOPE_RAW_DATA[which][0][j][1],
SLOPE_RAW_DATA[which][0][j][2]);
}
if (wireframe)
glVertex3f(SLOPE_RAW_DATA[which][0][0][0],
SLOPE_RAW_DATA[which][0][0][1],
SLOPE_RAW_DATA[which][0][0][2]);
glEnd();
glColor3f(0.1f, 0.5f, 1);
// top
if (which != 42 && which != 45) {
if (wireframe)
glBegin(GL_LINE_STRIP);
else
glBegin(GL_QUADS);
for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][2][j][0],
SLOPE_RAW_DATA[which][2][j][1],
SLOPE_RAW_DATA[which][2][j][2]);
}
if (wireframe)
glVertex3f(SLOPE_RAW_DATA[which][2][0][0],
SLOPE_RAW_DATA[which][2][0][1],
SLOPE_RAW_DATA[which][2][0][2]);
glEnd();
}
glColor3f(1, 0.2f, 0.5f);
// bottom
if (which != 41 && which != 46) {
if (wireframe)
glBegin(GL_LINE_STRIP);
else
glBegin(GL_QUADS);
for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][1][j][0],
SLOPE_RAW_DATA[which][1][j][1],
SLOPE_RAW_DATA[which][1][j][2]);
}
if (wireframe)
glVertex3f(SLOPE_RAW_DATA[which][1][0][0],
SLOPE_RAW_DATA[which][1][0][1],
SLOPE_RAW_DATA[which][1][0][2]);
glEnd();
}
glColor3f(0.4f, 0.1f, 0.6f);
// left
if (which != 44 && which != 48) {
if (wireframe)
glBegin(GL_LINE_STRIP);
else
glBegin(GL_QUADS);
for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][3][j][0],
SLOPE_RAW_DATA[which][3][j][1],
SLOPE_RAW_DATA[which][3][j][2]);
}
if (wireframe)
glVertex3f(SLOPE_RAW_DATA[which][3][0][0],
SLOPE_RAW_DATA[which][3][0][1],
SLOPE_RAW_DATA[which][3][0][2]);
glEnd();
}
glColor3f(0.8f, 0.6f, 0.2f);
// right
if (which != 43 && which != 47) {
if (wireframe)
glBegin(GL_LINE_STRIP);
else
glBegin(GL_QUADS);
for (int j=0; j < 4; j++) {
glVertex3f(SLOPE_RAW_DATA[which][4][j][0],
SLOPE_RAW_DATA[which][4][j][1],
SLOPE_RAW_DATA[which][4][j][2]);
}
if (wireframe)
glVertex3f(SLOPE_RAW_DATA[which][4][0][0],
SLOPE_RAW_DATA[which][4][0][1],
SLOPE_RAW_DATA[which][4][0][2]);
glEnd();
}
SDL_GL_SwapBuffers(); SDL_GL_SwapBuffers();
} }
void run_init(const char* prg) {
PHYSFS_init("blockview");
PHYSFS_addToSearchPath("gtadata.zip", 1);
PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1);
OpenGL::Screen & screen = OpenGL::ScreenHolder::Instance();
screen.activate(arg_screen_w, arg_screen_h);
SDL_EnableKeyRepeat( 100, SDL_DEFAULT_REPEAT_INTERVAL );
OpenGTA::MainMsgHolder::Instance().load("ENGLISH.FXT");
OpenGTA::MapHolder::Instance().load(map_file);
OpenGL::CameraHolder::Instance().setVectors(e, c, u);
}
void run_main() { void run_main() {
SDL_Event event; SDL_Event event;
int paused = 0; int paused = 0;
PHYSFS_init("mapview"); PHYSFS_init("blockview");
PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1); PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1);
glPolygonMode(GL_FRONT, GL_FILL);
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
//glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glEnable(GL_ALPHA_TEST);
//glDisable(GL_DEPTH_TEST);
map = new OpenGTA::MapViewGL();
map->loadMap("NYC.CMP", "STYLE001.GRY");
while(!global_Done && !global_EC) { while(!global_Done && !global_EC) {
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
@ -326,17 +218,11 @@ void run_main() {
handleKeyPress(&event.key.keysym); handleKeyPress(&event.key.keysym);
break; break;
case SDL_VIDEORESIZE: case SDL_VIDEORESIZE:
screen = SDL_SetVideoMode( event.resize.w,
event.resize.h, 32, videoFlags );
if (!screen)
ERROR("Failed to set video mode after resize event");
resize(event.resize.w, event.resize.h);
break; break;
case SDL_QUIT: case SDL_QUIT:
global_Done = 1; global_Done = 1;
break; break;
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
std::cout << "Mouse move: x " << float(event.motion.x)/screen->w << " y " << float(event.motion.y)/screen->h << std::endl;
break; break;
default: default:
break; break;

54
tools/bug_parser.awk Normal file
View File

@ -0,0 +1,54 @@
BEGIN {
in_record = 1
bug_num = 0
}
{
if ($1 ~ /^\%\% *$/) {
# print "RECORD END"
if (length(bug_status) == 0) {
bug_status = "open"
}
if (length(bug_has_image) == 0) {
pr_image_str = ""
}
else {
pr_image_str = "image: <a href=\"" bug_has_image "\">" bug_has_image "</a>"
}
print "<div class=\"a_bug\"><a name=\"bug_" bug_num "\"></a>"
print " <span class=\"bug_n\">#" bug_num "</span> &nbsp; <span class=\"bug_t\">" bug_title "</span><br>"
print " <span class=\"bug_s\">status: " bug_status "</span> &nbsp; <span>" pr_image_str "</span><br>"
print " <span class=\"bug_d\">" bug_descr "</span>"
print "</div>"
print "<br>"
}
if ($1 == "Bug:") {
sub(/^Bug: /, "", $0)
bug_title = $0
in_record = 2
bug_has_image = ""
bug_descr = ""
bug_status = ""
bug_num = bug_num + 1
}
else if ($1 == "Image:") {
bug_has_image = $2
}
else if ($1 == "Status:") {
bug_status = $2
}
else {
if (in_record == 2) {
if (length(bug_descr) > 0) {
if (length($0) == 0) {
bug_descr = bug_descr "<br>"
}
else {
bug_descr = bug_descr " " $0
}
}
else {
bug_descr = $0
}
}
}
}

52
tools/build_svg_rect.sh Executable file
View File

@ -0,0 +1,52 @@
#!/bin/bash
function print_header() {
cat <<EOF
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="$WIDTH" height="$HEIGHT" version="1.1"
xmlns="http://www.w3.org/2000/svg">
EOF
}
function print_rect() {
local x=$1
local y=$2
local w=$3
local h=$4
local col=$5
cat <<EOF
<rect x="$x" y="$y" width="$w" height="$h"
style="fill:rgb($col);stroke-width:1;
stroke:rgb(0,0,0)"/>
EOF
}
WIDTH=200
HEIGHT=200
function print_rnd_col() {
foo=$(echo "$RANDOM % 4" | bc)
case $foo in
0)
echo "0,0,255";;
1)
echo "255,0,0";;
2)
echo "0,255,0";;
3)
echo "255,255,0";;
esac
}
if [ $# -gt 0 ]; then
print_header
fi
while [ $# -gt 0 ]; do
col=$(print_rnd_col)
print_rect $1 $2 $3 $4 $col
shift;shift;shift;shift
done
echo '</svg>'

86
tools/car_dump.cpp Normal file
View File

@ -0,0 +1,86 @@
#include <iostream>
#include <string>
#include <sstream>
#include "opengta.h"
#include "dataholder.h"
extern int global_EC;
extern int global_Done;
std::string map_file("undefined_map_file");
std::string style_file("undefined_style_file");
std::string msg_file("ENGLISH.FXT");
void on_exit() {
PHYSFS_deinit();
if (global_EC)
std::cerr << "Exiting after fatal problem - please see output above" << std::endl;
}
void parse_args(int argc, char* argv[]) {
#ifdef DUMP_CARS_IN_MAP
if (argc != 3) {
std::cout << "USAGE: " << argv[0] << " map-file style-file" << std::endl;
exit(1);
}
map_file = argv[1];
style_file = argv[2];
#else
if (argc != 2) {
std::cout << "USAGE: " << argv[0] << " style-file" << std::endl;
exit(1);
}
map_file = "";
style_file = argv[1];
#endif
}
void print_car(OpenGTA::GraphicsBase::CarInfo & ci) {
std::ostringstream ostr;
ostr << "car" << int(ci.model);
#define PRINT(c) << #c << ":" << ci.c << "|"
#define PRINTC(c) << #c << ":" << int(ci.c) << "|"
std::cout PRINT(width) PRINT(height) PRINT(depth)
PRINT(sprNum) PRINT(weightDescriptor) PRINT(maxSpeed) PRINT(minSpeed)
PRINT(acceleration) PRINT(braking) PRINT(grip) PRINT(handling)
// remaps
PRINTC(vtype) PRINTC(model) PRINTC(turning) PRINTC(damagable) <<
"model-name:" << OpenGTA::MainMsgHolder::Instance().get().getText(ostr.str()) << "|"
PRINTC(cx) PRINTC(cy) PRINT(moment)
PRINT(rbpMass) PRINT(g1_Thrust) PRINT(tyreAdhesionX) PRINT(tyreAdhesionY)
PRINT(handBrakeFriction) PRINT(footBrakeFriction) PRINT(frontBrakeBias)
PRINT(turnRatio) PRINT(driveWheelOffset) PRINT(steeringWheelOffset)
PRINT(backEndSlideValue) PRINT(handBrakeSlideValue)
PRINTC(convertible) PRINTC(engine) PRINTC(radio) PRINTC(horn) PRINTC(soundFunction)
PRINTC(fastChangeFlag) PRINT(numDoors);
#undef PRINT
#define PRINT(c) << #c << ":" << ci.door[i].c << "|"
for (int i = 0; i < ci.numDoors; i++) {
std::cout PRINT(rpx) PRINT(rpy) PRINT(object) PRINT(delta);
}
std::cout << "remap8:";
for (int i = 0 ; i < 12; i++) {
std::cout << int(ci.remap8[i]) << (i < 11 ? "," : "");
}
std::cout << std::endl;
}
void run_init(const char*) {
PHYSFS_init("mapview");
PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1);
PHYSFS_addToSearchPath("gtadata.zip", 1);
}
// dump all cars in style
void run_main() {
OpenGTA::MainMsgHolder::Instance().load(msg_file);
OpenGTA::StyleHolder::Instance().load(style_file);
OpenGTA::GraphicsBase & style = OpenGTA::StyleHolder::Instance().get();
std::cout << "DUMP_OBJ_INFO BEGIN" << std::endl;
for (size_t i = 0; i < style.carInfos.size(); ++i) {
OpenGTA::GraphicsBase::CarInfo * cinfo = style.carInfos[i];
assert(cinfo);
print_car(*cinfo);
}
}

90
tools/fxt.c Normal file
View File

@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
void encode();
void decode();
int count = 0;
void usage(const char* prg) {
printf("USAGE: %s [-e | -d] < src_file > target_file\n", prg);
exit(0);
}
int main(int argc, char* argv[]) {
int mode = 0;
if (argc == 2) {
if (argv[1][1] == 'd')
mode = 1;
if (argv[1][1] == 'e')
mode = 2;
}
else
usage(argv[0]);
switch (mode) {
case 1:
decode();
break;
case 2:
encode();
break;
default:
usage(argv[0]);
break;
}
}
void decode() {
int c;
int addVal = 0;
while ((c = getchar()) != EOF) {
c--;
if (count <= 7)
c -= (0x63 << count);
if (c == 195) {
addVal = 64;
// fprintf(stderr, "addval after %i bytes\n", count);
}
else {
c += addVal;
/* if (addVal)
fprintf(stderr, "decoding-addval %i %i\n", c, c - addVal);
else
fprintf(stderr, "decoding: %i\n", (unsigned char)c);
*/
addVal = 0;
if (c == 0)
c = '\n';
putchar(c);
}
count++;
}
}
void encode_out(int v) {
if (count <= 7)
v += (0x63 << count);
v++;
putchar(v);
}
void encode() {
int c;
count = 0;
while ((c = getchar()) != EOF) {
if (c == '\n') {
c = 0;
}
if (c >= 192) {
int _c = 195;
encode_out(_c);
c -= 64;
encode_out(c);
}
else {
encode_out(c);
}
count++;
}
}

10
tools/label_screenshot.sh Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
in=$1
out=$1.new
convert $in -fill white -box '#00000080' \
-gravity North -annotate +0+10 ' ~Scumbag City~ by Pennywise ' \
-pointsize 20 $out

View File

@ -1,7 +1,60 @@
#include <cassert> #include <cassert>
#include <sstream>
#include "opengta.h" #include "opengta.h"
#include "dataholder.h"
#include "log.h" #include "log.h"
uint32_t green = 0x00dd00ff;
uint32_t red = 0xdd0000ff;
uint32_t blue = 0x0000ddff;
uint32_t field = green;
uint32_t building = 0xdf9f6fff;
uint32_t water = blue;
uint32_t road = 0xdadadaff;
uint32_t pavement = 0x8a9aa0ff;
uint32_t map_color[] = {
0x000000ff,
water,
road,
pavement,
field,
building,
0xffffffff,
0xff0000ff
};
void save_map_level(OpenGTA::Map & map, size_t level, const char* out_prefix) {
SDL_Surface* surface = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCALPHA,
256, 256, 32,// rmask, gmask, bmask, amask);
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
SDL_LockSurface(surface);
uint32_t* dst = static_cast<uint32_t*>(surface->pixels);
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++) {
PHYSFS_uint16 emptycount = map.getNumBlocksAtNew(j,i);
if (level < emptycount) {
OpenGTA::Map::BlockInfo* bi = map.getBlockAtNew(j, i, level);
*dst = map_color[bi->blockType()];
}
else {
*dst = map_color[0];
}
++dst;
}
}
SDL_UnlockSurface(surface);
std::ostringstream ostr;
ostr << out_prefix << "_" << level << ".bmp";
SDL_SaveBMP(surface, ostr.str().c_str());
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc < 2) { if (argc < 2) {
@ -15,32 +68,16 @@ int main(int argc, char* argv[]) {
PHYSFS_addToSearchPath("gtadata.zip", 1); PHYSFS_addToSearchPath("gtadata.zip", 1);
std::string map_filename(argv[1]); std::string map_filename(argv[1]);
OpenGTA::MainMsgHolder::Instance().load("ENGLISH.FXT");
OpenGTA::Map map(map_filename); OpenGTA::Map map(map_filename);
uint32_t green = 0x00dd00ff;
uint32_t red = 0xdd0000ff;
uint32_t blue = 0x0000ddff;
uint32_t field = green;
uint32_t building = 0xdf9f6fff;
uint32_t water = blue;
uint32_t road = 0xdadadaff;
uint32_t pavement = 0x8a9aa0ff;
uint32_t map_color[] = {
0x000000ff,
water,
road,
pavement,
field,
building,
0xffffffff,
0xff0000ff
};
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
for (size_t i = 0; i < 7; i++)
save_map_level(map, i, "out");
#if 0
// FIXME: doesn't work right // FIXME: doesn't work right
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define rmask 0xff000000 #define rmask 0xff000000
@ -102,6 +139,8 @@ int main(int argc, char* argv[]) {
} }
SDL_UnlockSurface(surface); SDL_UnlockSurface(surface);
SDL_SaveBMP(surface, "out.bmp"); SDL_SaveBMP(surface, "out.bmp");
#endif
SDL_Quit(); SDL_Quit();
return 0; return 0;

38
tools/package_binary.sh Normal file
View File

@ -0,0 +1,38 @@
#!/bin/bash
DLL_NAMES_W32=*.dll #"SDL.dll"
function binary() {
local ex_name=$1
if [ "$HOST" == "WIN32" ]; then
echo $ex_name".exe"
echo $DLL_NAMES_W32
else
echo $ex_name
fi
}
function host_txt() {
if [ "$HOST" == "WIN32" ]; then
unix2dos $@
fi
echo "$@"
}
function list_files() {
binary viewer
echo licenses/*
host_txt license.txt readme.txt cvs_changelog.txt
host_txt doc/using_mods.txt
}
R_DATE=$(cat ogta_version)
if [ "$HOST" == "WIN32" ]; then
ZIP_FILE_NAME=ogta_sneak-preview-${R_DATE}_win32
list_files | xargs zip $ZIP_FILE_NAME
else
TAR_FILE_NAME=ogta_sneak-preview-${R_DATE}_linux.tar.bz2
list_files | xargs tar jvcf $TAR_FILE_NAME
fi

25
tools/picasa_ls.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
TMP_FILE=/tmp/picasa_lst.$$
function fetch() {
wget -O $TMP_FILE 'http://picasaweb.google.com/data/feed/base/user/under.northern.sky/albumid/5015283825893823185?kind=photo&alt=rss&hl=en_US'
}
function extract() {
local _file=$1
echo 'cat /rss/channel/item[*]/enclosure|/rss/channel/item[*]/link' \
| xmllint --shell $_file | grep http | sed \
-e 's|^.*url="||' -e 's|".*$||' -e 's|<\/*link>||g'
}
fetch
extract $TMP_FILE | {
while read a; do
basename $a
read b
echo $b
echo
done
}
rm -f $TMP_FILE

34
tools/plot_stats.sh Executable file
View File

@ -0,0 +1,34 @@
#!/bin/bash
if [ ! -e stats ]; then
echo "start me in the archive dir after creatings 'stats'"
exit 1
fi
sh ../tools/stats_recalc.sh < stats > stats2
gnuplot <<EOF
set timefmt "%Y-%m-%d"
set xdata time
set format x "%Y-%m-%d"
set yr[0:260]
set ytics 20
set y2tics 0,10,40
set grid ytics y2tics
plot "stats2" using 1:2 title "total size [KB]" with points 1 2
replot "stats2" using 1:2 notitle with lines 1
replot "stats2" using 1:3 title "files" with points 2 2
replot "stats2" using 1:3 notitle with lines 2
replot "stats2" using 1:4 title "code lines [K]" with points 7 2
replot "stats2" using 1:4 notitle with lines 7
set output "stats_plot.svg"
set terminal svg size 800 400
replot
EOF
../tools/replace_in_files.sh "s/black/silver/g" stats_plot.svg
inkscape -e stats_plot.png stats_plot.svg
rm stats2 stats_plot.svg

31
tools/projects_stats.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/bash
infile=$1
if [ ! -e $infile ]; then
echo "gimme a tar.gz"
exit 1
fi
archive_size=$(stat -c "%s" $infile)
tmpdir=/tmp/work_`basename $0`_$$
mkdir $tmpdir
bzip2 -cd $infile | ( cd $tmpdir ; tar x)
cd $tmpdir/ogta || exit 1
num_files=$(find -type f | wc -l)
num_code_lines=$(find -name "*.cpp" -o -name "*.c" -o -name "*.hpp" -o -name "*.h" \
| xargs wc -l | tail -1 | sed -e 's/^ *//' -e 's/ total//')
filename=$(basename $infile)
filename=${filename%%.tar.bz2}
filename=${filename##ogta_src_}
echo "$filename $archive_size $num_files $num_code_lines"
rm -rf $tmpdir

18
tools/raw_images.m4 Normal file
View File

@ -0,0 +1,18 @@
define(`FIND_AT', `(iname.find("$1") == $2)')dnl
define(`CONDITION', `if ($1) {
$2
}')dnl
define(`RESULT', `width = $1; height = $2;')dnl
dnl
CONDITION(`FIND_AT(`CUT', 0) && FIND_AT(`.RA', 4)', `RESULT(640, 480)')
CONDITION(`FIND_AT(`F_BMG.RA', 0)', `RESULT(100, 50)')
CONDITION(`FIND_AT(`F_DMA.RA', 0)', `RESULT(78, 109)')
CONDITION(`FIND_AT(`F_LOGO', 0) && FIND_AT(`.RA', 7)', `RESULT(640, 168)')
CONDITION(`FIND_AT(`F_LOWER', 0) && FIND_AT(`.RA', 8)', `RESULT(640, 312)')
CONDITION(`FIND_AT(`F_PLAYN.RA', 0)', `RESULT(180, 50)')
CONDITION(`FIND_AT(`F_PLAY', 0) && FIND_AT(`.RA', 7)', `RESULT(102, 141)')
CONDITION(`FIND_AT(`F_UPPER.RA', 0)', `RESULT(640, 168)')
dnl
dnl see: http://membres.lycos.fr/dolmen/gta/raw.html
dnl flag2.raw 20x200
dnl joy.raw 19x18

6
tools/stats_recalc.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
while read a b c d; do
b=$(echo "$b / 1024" | bc -l)
d=$(echo "$d / 1000" | bc -l)
echo "$a $b $c $d"
done

View File

@ -40,6 +40,12 @@ namespace Util {
return 360.0f + res; return 360.0f + res;
return res; return res;
} }
float xz_turn_angle(const Vector3D & from, const Vector3D & to) {
Vector3D rel_to(to);
rel_to = rel_to - from;
double res = atan(rel_to.x / rel_to.z) * 180.0f / M_PI;
return res;
}
bool CellIterator::isValid() const { bool CellIterator::isValid() const {
if (x < 0 || x > 255) if (x < 0 || x > 255)
@ -51,7 +57,7 @@ namespace Util {
return (z < mapRef.getNumBlocksAtNew(x, y)); return (z < mapRef.getNumBlocksAtNew(x, y));
} }
OpenGTA::Map::BlockInfo & CellIterator::getBlock() { OpenGTA::Map::BlockInfo & CellIterator::getBlock() const {
assert(isValid()); assert(isValid());
return *mapRef.getBlockAtNew(x, y, z); return *mapRef.getBlockAtNew(x, y, z);
} }
@ -61,4 +67,76 @@ namespace Util {
return (IABS(x - o.x) + IABS(y - o.y) + IABS(z - o.z)); return (IABS(x - o.x) + IABS(y - o.y) + IABS(z - o.z));
} }
bool CellIterator::isBlockType(uint8_t t) const {
if (!isValid())
return false;
return (getBlock().blockType() == t);
}
std::pair<bool, CellIterator> CellIterator::findTypeInCol(uint8_t t) const {
if (isBlockType(t))
return std::make_pair<bool, CellIterator>(true, *this);
CellIterator below = down();
while (below.isValid()) {
if (below.isBlockType(t))
return std::make_pair<bool, CellIterator>(true, below);
below = below.down();
}
CellIterator above = up();
while (above.isValid()) {
if (above.isBlockType(t))
return std::make_pair<bool, CellIterator>(true, above);
above = above.up();
}
return std::make_pair<bool, CellIterator>(false, *this);
}
std::pair<bool, CellIterator> CellIterator::findNeighbourWithType(
uint8_t t, float angle_hint) {
assert(isValid());
if (angle_hint >= 315 || angle_hint < 45) {
std::pair<bool, CellIterator> p = top().findTypeInCol(t);
// if (p.first) INFO << p.second.x << " " << p.second.y << " " << p.second.z << std::endl;
if (p.first) return p;
}
if (angle_hint >= 0 || angle_hint < 90) {
std::pair<bool, CellIterator> p = top().right().findTypeInCol(t);
// if (p.first) INFO << p.second.x << " " << p.second.y << " " << p.second.z << std::endl;
if (p.first) return p;
}
if (angle_hint >= 45 && angle_hint < 135) {
std::pair<bool, CellIterator> p = right().findTypeInCol(t);
// if (p.first) INFO << p.second.x << " " << p.second.y << " " << p.second.z << std::endl;
if (p.first) return p;
}
if (angle_hint >= 90 && angle_hint < 180) {
std::pair<bool, CellIterator> p = right().bottom().findTypeInCol(t);
// if (p.first) INFO << p.second.x << " " << p.second.y << " " << p.second.z << std::endl;
if (p.first) return p;
}
if (angle_hint >= 135 && angle_hint < 225) {
std::pair<bool, CellIterator> p = bottom().findTypeInCol(t);
// if (p.first) INFO << p.second.x << " " << p.second.y << " " << p.second.z << std::endl;
if (p.first) return p;
}
if (angle_hint >= 180 && angle_hint < 270) {
std::pair<bool, CellIterator> p = left().bottom().findTypeInCol(t);
// if (p.first) INFO << p.second.x << " " << p.second.y << " " << p.second.z << std::endl;
if (p.first) return p;
}
if (angle_hint >= 225 && angle_hint < 315) {
std::pair<bool, CellIterator> p = left().findTypeInCol(t);
// if (p.first) INFO << p.second.x << " " << p.second.y << " " << p.second.z << std::endl;
if (p.first) return p;
}
if (angle_hint >= 270 && angle_hint < 360) {
std::pair<bool, CellIterator> p = top().left().findTypeInCol(t);
// if (p.first) INFO << p.second.x << " " << p.second.y << " " << p.second.z << std::endl;
if (p.first) return p;
}
return std::make_pair<bool, CellIterator>(false, *this);
}
} }

View File

@ -31,6 +31,7 @@
namespace Util { namespace Util {
float distance(const Vector3D & p1, const Vector3D & p2); float distance(const Vector3D & p1, const Vector3D & p2);
float xz_angle(const Vector3D & from, const Vector3D & to); float xz_angle(const Vector3D & from, const Vector3D & to);
float xz_turn_angle(const Vector3D & from, const Vector3D & to);
class CellIterator { class CellIterator {
public: public:
@ -89,8 +90,11 @@ namespace Util {
p.z -= 1; p.z -= 1;
return p; return p;
} }
bool isBlockType(uint8_t t) const;
std::pair<bool, CellIterator> findTypeInCol(uint8_t t) const;
std::pair<bool, CellIterator> findNeighbourWithType(uint8_t t, float angle_hint);
int x, y, z; int x, y, z;
OpenGTA::Map::BlockInfo & getBlock(); OpenGTA::Map::BlockInfo & getBlock() const;
private: private:
OpenGTA::Map & mapRef; OpenGTA::Map & mapRef;
}; };

View File

@ -26,6 +26,7 @@
#include "m_exceptions.h" #include "m_exceptions.h"
#include "file_helper.h" #include "file_helper.h"
#include "buffercache.h" #include "buffercache.h"
#include "log.h"
#ifndef OGTA_DEFAULT_DATA_PATH #ifndef OGTA_DEFAULT_DATA_PATH
#define OGTA_DEFAULT_DATA_PATH "gtadata.zip" #define OGTA_DEFAULT_DATA_PATH "gtadata.zip"
@ -117,4 +118,24 @@ namespace Util {
PHYSFS_close(fd); PHYSFS_close(fd);
return buffer; return buffer;
} }
const std::string FileHelper::lang2MsgFilename(const char *l) {
assert(l);
std::string lang(l);
if (lang.size() > 2)
lang = lang.substr(0, 2);
std::transform(lang.begin(), lang.end(), lang.begin(), tolower);
if (lang == "en")
return std::string("ENGLISH.FXT");
else if (lang == "de")
return std::string("GERMAN.FXT");
else if (lang == "fr")
return std::string("FRENCH.FXT");
else if (lang == "it")
return std::string("ITALIAN.FXT");
WARN << "Unknown language: " << l << " - falling back to english"
<< std::endl;
return std::string("ENGLISH.FXT");
}
} }

View File

@ -40,6 +40,7 @@ namespace Util {
bool existsInVFS(const std::string & file) const; bool existsInVFS(const std::string & file) const;
PHYSFS_file* openReadVFS(const std::string & file) const; PHYSFS_file* openReadVFS(const std::string & file) const;
unsigned char* bufferFromVFS(PHYSFS_file*) const; unsigned char* bufferFromVFS(PHYSFS_file*) const;
static const std::string lang2MsgFilename(const char* l);
private: private:
std::string baseDataPath; std::string baseDataPath;
std::string modDataPath; std::string modDataPath;

559
util/gui.cpp Normal file
View File

@ -0,0 +1,559 @@
#include "gui.h"
#include "m_exceptions.h"
#include "dataholder.h"
#include "gl_spritecache.h"
#include "gl_screen.h"
#ifdef WITH_LUA
#include "lua_vm.h"
#endif
#include <sstream>
#include "localplayer.h"
extern float screen_gamma;
namespace GUI {
Object::Object(const SDL_Rect & r) :
id(0), rect(), color(), borderColor(), drawBorder(false),
manager(ManagerHolder::Instance()) {
copyRect(r);
color.r = 255; color.g = 255; color.b = 255; color.unused = 255;
}
Object::Object(const size_t Id, const SDL_Rect & r) :
id(Id), rect(), color(), borderColor(), drawBorder(false),
manager(ManagerHolder::Instance()) {
copyRect(r);
color.r = 255; color.g = 255; color.b = 255; color.unused = 255;
}
Object::Object(const size_t Id, const SDL_Rect & r, const SDL_Color & c) :
id(Id), rect(), color(), borderColor(), drawBorder(false),
manager(ManagerHolder::Instance()) {
copyRect(r);
copyColor(c);
}
void Object::draw() {
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4ub(color.r, color.g, color.b, color.unused);
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glVertex2i(rect.x, rect.y);
glVertex2i(rect.x + rect.w, rect.y);
glVertex2i(rect.x + rect.w, rect.y + rect.h);
glVertex2i(rect.x, rect.y + rect.h);
glEnd();
if (drawBorder)
draw_border();
glDisable(GL_BLEND);
}
void Object::draw_border() {
glColor4ub(borderColor.r, borderColor.g, borderColor.b,
borderColor.unused);
glBegin(GL_LINE_LOOP);
glVertex2i(rect.x, rect.y);
glVertex2i(rect.x + rect.w, rect.y);
glVertex2i(rect.x + rect.w, rect.y + rect.h);
glVertex2i(rect.x, rect.y + rect.h);
glEnd();
}
void Object::copyRect(const SDL_Rect & src) {
rect.x = src.x;
rect.y = src.y;
rect.w = src.w;
rect.h = src.h;
}
void Object::copyColor(const SDL_Color & src) {
color.r = src.r;
color.g = src.g;
color.b = src.b;
color.unused = src.unused;
}
void TexturedObject::draw() {
if (texId == 0)
return;
const OpenGL::PagedTexture & tex = manager.getCachedImage(texId);
glColor4ub(color.r, color.g, color.b, color.unused);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex.inPage);
glBegin(GL_QUADS);
glTexCoord2f(tex.coords[0].u, tex.coords[1].v);
glVertex2i(rect.x, rect.y);
glTexCoord2f(tex.coords[1].u, tex.coords[1].v);
glVertex2i(rect.x + rect.w, rect.y);
glTexCoord2f(tex.coords[1].u, tex.coords[0].v);
glVertex2i(rect.x + rect.w, rect.y + rect.h);
glTexCoord2f(tex.coords[0].u, tex.coords[0].v);
glVertex2i(rect.x, rect.y + rect.h);
glEnd();
glDisable(GL_TEXTURE_2D);
if (drawBorder)
draw_border();
}
void AnimatedTextureObject::draw() {
if (!animation)
animation = manager.findAnimation(animId);
assert(animation);
size_t texId = animation->getCurrentFrame();
const OpenGL::PagedTexture & tex = manager.getCachedImage(texId);
glColor4ub(color.r, color.g, color.b, color.unused);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex.inPage);
glBegin(GL_QUADS);
glTexCoord2f(tex.coords[0].u, tex.coords[1].v);
glVertex2i(rect.x, rect.y);
glTexCoord2f(tex.coords[1].u, tex.coords[1].v);
glVertex2i(rect.x + rect.w, rect.y);
glTexCoord2f(tex.coords[1].u, tex.coords[0].v);
glVertex2i(rect.x + rect.w, rect.y + rect.h);
glTexCoord2f(tex.coords[0].u, tex.coords[0].v);
glVertex2i(rect.x, rect.y + rect.h);
glEnd();
glDisable(GL_TEXTURE_2D);
if (drawBorder)
draw_border();
}
void Label::draw() {
glPushMatrix();
glColor4ub(color.r, color.g, color.b, color.unused);
glEnable(GL_TEXTURE_2D);
if (align == 0) {
glTranslatef(rect.x, rect.y, 0);
rect.w = uint16_t(font->drawString(text));
}
else if (align == 1) {
glTranslatef(rect.x, rect.y, 0);
rect.w = uint16_t(font->drawString_r2l(text));
}
rect.h = font->getHeight();
glPopMatrix();
/*
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINE_STRIP);
glVertex2i(rect.x, rect.y);
glVertex2i(rect.x + rect.w, rect.y);
glVertex2i(rect.x + rect.w, rect.y + rect.h);
glVertex2i(rect.x, rect.y + rect.h);
glVertex2i(rect.x, rect.y);
glEnd();
*/
glDisable(GL_TEXTURE_2D);
if (drawBorder)
draw_border();
}
void Pager::draw() {
const OpenGL::PagedTexture & tex = manager.getCachedImage(texId);
glColor4ub(color.r, color.g, color.b, color.unused);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex.inPage);
glBegin(GL_QUADS);
glTexCoord2f(tex.coords[0].u, tex.coords[1].v);
glVertex2i(rect.x, rect.y);
glTexCoord2f(tex.coords[1].u, tex.coords[1].v);
glVertex2i(rect.x + rect.w, rect.y);
glTexCoord2f(tex.coords[1].u, tex.coords[0].v);
glVertex2i(rect.x + rect.w, rect.y + rect.h);
glTexCoord2f(tex.coords[0].u, tex.coords[0].v);
glVertex2i(rect.x, rect.y + rect.h);
glEnd();
glScissor(rect.x, rect.y, rect.w, rect.h);
glEnable(GL_SCISSOR_TEST);
glPushMatrix();
glColor4ub(color.r, color.g, color.b, color.unused);
glTranslatef(rect.x+offset, rect.y+4, 0);
int slen = (int)font->drawString("test - hello world, this is a really long message. it will not end. never... or maybe sometime, but not yet. The end.");
if (slen + offset < -10) {
color.unused = 0;
manager.remove(this);
}
INFO << slen <<" " << offset << std::endl;
glPopMatrix();
glDisable(GL_SCISSOR_TEST);
glDisable(GL_TEXTURE_2D);
if (drawBorder)
draw_border();
}
void Pager::update(Uint32 ticks) {
offset -= 1;
//if (offset < -50)
// color.unused = 0;
}
void Manager::draw() {
GuiObjectListMap::iterator layer_it = guiLayers.begin();
while (layer_it != guiLayers.end()) {
GuiObjectList & inThisLayer = layer_it->second;
for (GuiObjectList::iterator obj_it = inThisLayer.begin();
obj_it != inThisLayer.end(); ++obj_it) {
Object * obj = *obj_it;
obj->draw();
}
++layer_it;
}
glColor4f(1, 1, 1, 1);
glEnable(GL_TEXTURE_2D);
}
Manager::~Manager() {
clearObjects();
clearCache();
}
void Manager::clearObjects() {
INFO << "clearing gui objects" << std::endl;
GuiObjectListMap::iterator layer_it = guiLayers.begin();
while (layer_it != guiLayers.end()) {
GuiObjectList & list = layer_it->second;
for (GuiObjectList::iterator i = list.begin(); i != list.end(); ++i) {
delete *i;
}
list.clear();
++layer_it;
}
guiLayers.clear();
}
void Manager::clearCache() {
INFO << "clearing gui texture cache" << std::endl;
for (GuiTextureCache::iterator i = texCache.begin(); i != texCache.end(); ++i) {
OpenGL::PagedTexture & p = i->second;
glDeleteTextures(1, &p.inPage);
}
texCache.clear();
for (AnimationMap::iterator i = guiAnimations.begin(); i != guiAnimations.end(); ++i) {
delete i->second;
}
guiAnimations.clear();
}
const OpenGL::PagedTexture & Manager::getCachedImage(size_t Id) {
GuiTextureCache::iterator i = findByCacheId(Id);
if (i == texCache.end()) {
std::ostringstream o;
o << "cached texture id " << int(Id);
throw E_UNKNOWNKEY(o.str());
}
return i->second;
}
Manager::GuiTextureCache::iterator Manager::findByCacheId(const size_t & Id) {
return texCache.find(Id);
}
Manager::GuiObjectListMap::iterator Manager::findLayer(uint8_t l) {
return guiLayers.find(l);
}
void Manager::cacheImageRAW(const std::string & file, size_t k) {
texCache.insert(std::make_pair<size_t, OpenGL::PagedTexture>(k, ImageUtil::loadImageRAW(file)));
}
void Manager::cacheImageRAT(const std::string & file, const std::string & palette, size_t k) {
texCache.insert(std::make_pair<size_t, OpenGL::PagedTexture>(k,
ImageUtil::loadImageRATWithPalette(file, palette)));
}
ImageUtil::WidthHeightPair Manager::cacheStyleArrowSprite(const size_t id, int remap) {
OpenGTA::GraphicsBase & graphics = OpenGTA::StyleHolder::Instance().get();
PHYSFS_uint16 t = graphics.spriteNumbers.reIndex(id, OpenGTA::GraphicsBase::SpriteNumbers::ARROW);
OpenGTA::GraphicsBase::SpriteInfo * info = graphics.getSprite(t);
texCache.insert(std::make_pair<size_t, OpenGL::PagedTexture>(
id, OpenGL::SpriteCacheHolder::Instance().createSprite(size_t(t), remap, 0, info)
));
return ImageUtil::WidthHeightPair(info->w, info->h);
}
#ifdef WITH_SDL_IMAGE
void Manager::cacheImageSDL(const std::string & file, size_t k) {
texCache.insert(std::make_pair<size_t, OpenGL::PagedTexture>(k,
ImageUtil::loadImageSDL(file)));
}
#endif
void Manager::add(Object * obj, uint8_t onLevel) {
GuiObjectListMap::iterator l = findLayer(onLevel);
if (l == guiLayers.end()) {
GuiObjectList list;
list.push_back(obj);
guiLayers.insert(std::make_pair<uint8_t, GuiObjectList>(onLevel, list));
return;
}
GuiObjectList & list = l->second;
list.push_back(obj);
}
void Manager::remove(Object * obj) {
for (GuiObjectListMap::iterator l = guiLayers.begin(); l != guiLayers.end(); ++l) {
GuiObjectList & list = l->second;
for (GuiObjectList::iterator m = list.begin(); m != list.end(); ++m) {
Object * o = *m;
if (o == obj) {
delete o;
list.erase(m);
return;
}
}
}
throw E_UNKNOWNKEY("not a managed object-ptr");
}
Object* Manager::findObject(const size_t id) {
for (GuiObjectListMap::iterator l = guiLayers.begin(); l != guiLayers.end(); ++l) {
GuiObjectList & list = l->second;
for (GuiObjectList::iterator m = list.begin(); m != list.end(); ++m) {
Object * o = *m;
if (o->id == id)
return o;
}
}
std::ostringstream o;
o << "object by id " << int(id);
throw E_UNKNOWNKEY(o.str());
return 0;
}
void Manager::removeById(const size_t id) {
Object * o = findObject(id);
if (o)
remove(o);
//else
// ERROR << "failed to find object " << id << " - cannot remove it" << std::endl;
}
bool Manager::isInside(Object & obj, Uint16 x, Uint16 y) const {
if ((obj.rect.x <= x) && (x <= obj.rect.x + obj.rect.w) &&
(obj.rect.y <= y) && (y <= obj.rect.y + obj.rect.h))
return true;
return false;
}
void Manager::receive(SDL_MouseButtonEvent & mb_event) {
Uint32 sh = OpenGL::ScreenHolder::Instance().getHeight();
GuiObjectListMap::reverse_iterator l = guiLayers.rbegin();
while (l != guiLayers.rend()) {
GuiObjectList & list = l->second;
for (GuiObjectList::iterator i = list.begin(); i != list.end(); ++i) {
Object * obj = *i;
if (isInside(*obj, mb_event.x, sh - mb_event.y)) {
// std::cout << "mouse inside obj id: " << obj->id << " at " << mb_event.x << "," << mb_event.y << std::endl;
obj->receive(mb_event);
return;
}
}
++l;
}
}
void Manager::update(uint32_t nowticks) {
for (AnimationMap::iterator i = guiAnimations.begin(); i != guiAnimations.end(); ++i) {
i->second->update(nowticks);
}
GuiObjectListMap::iterator layer_it = guiLayers.begin();
while (layer_it != guiLayers.end()) {
GuiObjectList & inThisLayer = layer_it->second;
for (GuiObjectList::iterator obj_it = inThisLayer.begin();
obj_it != inThisLayer.end(); ++obj_it) {
Object * obj = *obj_it;
obj->update(nowticks);
}
++layer_it;
}
}
Animation* Manager::findAnimation(uint16_t id) {
AnimationMap::iterator i = guiAnimations.find(id);
return i->second;
}
void Manager::createAnimation(const std::vector<uint16_t> & indices, uint16_t fps, size_t k) {
Animation * anim = new Animation(indices, fps);
guiAnimations.insert(std::make_pair<size_t, Animation*>(k, anim));
anim->set(Util::Animation::PLAY_FORWARD, Util::Animation::LOOP);
}
uint16_t Animation::getCurrentFrame() {
return indices[getCurrentFrameNumber()];
}
const int WEAPON_DISPLAY_ID = 100;
const SDL_Rect sdl_rect(size_t a, size_t b, size_t c, size_t d) {
SDL_Rect rect;
rect.x = a;
rect.y = b;
rect.w = c;
rect.h = d;
return rect;
}
WeaponDisplay::WeaponDisplay(const SDL_Rect & r) : Object(WEAPON_DISPLAY_ID, r),
img(sdl_rect(r.x+2, r.y+2, r.w - 4, r.h - 4), 0),
label(sdl_rect(r.x+2, r.y+r.h, r.w - 4, r.h - 4), "", "F_MTEXT.FON", 1) {
}
void WeaponDisplay::draw() {
img.draw();
label.draw();
}
size_t WeaponDisplay::getWeaponIdx(const size_t wt) {
if (wt == 0)
return 0;
if (wt < 5)
return 1000 + wt;
return 0;
}
void WeaponDisplay::setWeapon(const size_t wt) {
img.texId = getWeaponIdx(wt);
try {
manager.getCachedImage(img.texId);
}
catch (const Util::UnknownKey & ek) {
WARN << "GUI image for weapon " << wt << " not loaded - retrying" << std::endl;
manager.cacheStyleArrowSprite(img.texId, -1);
}
}
void ScrollBar::draw() {
Object::draw();
glColor3ub(innerColor.r, innerColor.g, innerColor.b);
glBegin(GL_QUADS);
glVertex2i(rect.x+2, rect.y+2);
glVertex2i(rect.x + int(rect.w * value) -2, rect.y+2);
glVertex2i(rect.x + int(rect.w * value) -2, rect.y + rect.h-2);
glVertex2i(rect.x+2, rect.y + rect.h-2);
glEnd();
}
void ScrollBar::receive(SDL_MouseButtonEvent & mb_event) {
value = (mb_event.x - rect.x) / float(rect.w - 4);
INFO << value << std::endl;
if (changeCB)
changeCB(value * 2);
else
WARN << "No callback function set - I ain't seen nothing" <<
std::endl;
/*
SDL_SetGamma(value * 2, value * 2, value * 2);
Object * o = ManagerHolder::Instance().findObject(101);
if (o) {
std::ostringstream os;
os << "Gamma: " << value * 2;
static_cast<Label*>(o)->text = os.str();
}*/
}
void screen_gamma_callback(float v) {
screen_gamma = v;
SDL_SetGamma(v, v, v);
#ifdef WITH_LUA
OpenGTA::Script::LuaVM & vm = OpenGTA::Script::LuaVMHolder::Instance();
lua_State *L = vm.getInternalState();
int top = lua_gettop(L);
lua_getglobal(L, "config");
if (lua_type(L, -1) != LUA_TTABLE) {
lua_pop(L, 1);
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setglobal(L, "config");
}
uint8_t sf = OpenGTA::StyleHolder::Instance().get().getFormat();
if (sf)
vm.setFloat("screen_gamma_g24", v);
else
vm.setFloat("screen_gamma_gry", v);
lua_settop(L, top);
#endif
Object * o = ManagerHolder::Instance().findObject(GAMMA_LABEL_ID);
if (o) {
std::ostringstream os;
os << "Gamma: " << v;
static_cast<Label*>(o)->text = os.str();
}
/*
Object * o2 = ManagerHolder::Instance().findObject(1001);
if (o2) {
static_cast<ImageStatusDisplay*>(o2)->number = screen_gamma * 3;
}*/
}
AnimStatusDisplay* wantedLevel = NULL;
Label* cashLabel = NULL;
void create_ingame_gui(bool is32bit) {
OpenGL::Screen & screen = OpenGL::ScreenHolder::Instance();
GUI::Manager & gm = ManagerHolder::Instance();
assert(!wantedLevel);
{
SDL_Rect r;
r.h = 32;
r.x = screen.getWidth() / 2 - 50;
r.y = screen.getHeight() - r.h;
r.w = 100;
SDL_Rect rs;
rs.x = rs.y = 0;
rs.w = rs.h = 16;
gm.cacheStyleArrowSprite(16, -1);
gm.cacheStyleArrowSprite(17, -1);
std::vector<uint16_t> anim2frames(2);
anim2frames[0] = 16;
anim2frames[1] = 17;
gm.createAnimation(anim2frames, 10, 2);
wantedLevel = new AnimStatusDisplay(WANTED_LEVEL_ID, r, rs, 2);
/*
wantedLevel->borderColor.r = wantedLevel->borderColor.g = wantedLevel->borderColor.b = wantedLevel->borderColor.unused = 255;
wantedLevel->drawBorder = 1;
*/
gm.add(wantedLevel, 50);
}
assert(!cashLabel);
{
SDL_Rect r;
r.x = screen.getWidth() - 5;
r.y = screen.getHeight() - 30;
cashLabel = new Label(GUI::CASH_ID, r, "0", "F_MTEXT.FON", 1);
cashLabel->align = 1;
gm.add(cashLabel, 50);
}
}
void update_ingame_gui_values() {
OpenGTA::PlayerController & pc = OpenGTA::LocalPlayer::Instance();
if (wantedLevel)
wantedLevel->number = pc.getWantedLevel();
if (cashLabel) {
std::ostringstream os;
os << pc.getCash();
cashLabel->text = os.str();
}
}
void remove_ingame_gui() {
GUI::Manager & gm = ManagerHolder::Instance();
if (wantedLevel)
gm.remove(wantedLevel);
wantedLevel = NULL;
if (cashLabel)
gm.remove(cashLabel);
cashLabel = NULL;
}
}

View File

@ -36,6 +36,18 @@ namespace GUI {
struct Object; struct Object;
class Animation; class Animation;
/** Wrapper around GUI elements.
*
* Contains a number of lists of objects; mouse click events can be delegated
* to any element. Elements are placed into "layers"; drawing is done from
* low to high (0 .. 255), clicked-inside is tested high to low (255 ... 0).
*
* Objects _should_ have a unique id (removeById only finds the first match),
* but this is neither ensured nor required.
*
* Finally there are helper functions (which are used by derived objects) to
* load/access images/animations.
*/
class Manager { class Manager {
public: public:
Manager() {} Manager() {}
@ -47,11 +59,13 @@ namespace GUI {
void draw(); void draw();
void clearObjects(); void clearObjects();
void clearCache(); void clearCache();
void cacheImageRAW(const std::string & file, size_t asId); void cacheImageRAW(const std::string & file, size_t id);
void cacheImageRAT(const std::string & file, const std::string & palette, size_t asId); void cacheImageRAT(const std::string & file, const std::string & palette, size_t id);
void cacheImageSDL(const std::string & file, size_t asId); #ifdef WITH_SDL_IMAGE
void cacheImageSDL(const std::string & file, size_t id);
#endif
ImageUtil::WidthHeightPair cacheStyleArrowSprite(const size_t id, int remap); ImageUtil::WidthHeightPair cacheStyleArrowSprite(const size_t id, int remap);
const OpenGL::PagedTexture & getCachedImage(size_t Id); const OpenGL::PagedTexture & getCachedImage(size_t id);
void receive(SDL_MouseButtonEvent & mb_event); void receive(SDL_MouseButtonEvent & mb_event);
Animation* findAnimation(uint16_t id); Animation* findAnimation(uint16_t id);
void createAnimation(const std::vector<uint16_t> & indices, uint16_t fps, size_t asAnimId); void createAnimation(const std::vector<uint16_t> & indices, uint16_t fps, size_t asAnimId);
@ -83,6 +97,8 @@ namespace GUI {
uint16_t getCurrentFrame(); uint16_t getCurrentFrame();
}; };
/** Base-object - Can be used to draw coloured area & border.
*/
struct Object { struct Object {
Object(const SDL_Rect & r); Object(const SDL_Rect & r);
Object(const size_t Id, const SDL_Rect & r); Object(const size_t Id, const SDL_Rect & r);
@ -91,10 +107,14 @@ namespace GUI {
size_t id; size_t id;
SDL_Rect rect; SDL_Rect rect;
SDL_Color color; SDL_Color color;
SDL_Color borderColor;
bool drawBorder;
void copyRect(const SDL_Rect & src); void copyRect(const SDL_Rect & src);
void copyColor(const SDL_Color & src); void copyColor(const SDL_Color & src);
virtual void draw(); virtual void draw();
virtual void update(Uint32 ticks) {} virtual void update(Uint32 ticks) {}
virtual void receive(SDL_MouseButtonEvent & mb_event) {}
void draw_border();
Manager & manager; Manager & manager;
}; };
@ -133,9 +153,11 @@ namespace GUI {
const std::string & fontFile, const size_t fontScale) : Object(Id, r), text(s) { const std::string & fontFile, const size_t fontScale) : Object(Id, r), text(s) {
OpenGL::DrawableFont & fnt = OpenGTA::FontCacheHolder::Instance().getFont(fontFile, fontScale); OpenGL::DrawableFont & fnt = OpenGTA::FontCacheHolder::Instance().getFont(fontFile, fontScale);
font = &fnt; font = &fnt;
align = 0;
} }
OpenGL::DrawableFont * font; OpenGL::DrawableFont * font;
std::string text; std::string text;
uint8_t align;
void draw(); void draw();
}; };
@ -154,5 +176,68 @@ namespace GUI {
std::string lastMsg; std::string lastMsg;
int offset; int offset;
}; };
struct WeaponDisplay : public Object {
public:
WeaponDisplay(const SDL_Rect & r);
void setWeapon(const size_t wt);
void draw();
private:
size_t getWeaponIdx(const size_t wt);
TexturedObject img;
Label label;
};
struct ScrollBar : public Object {
ScrollBar(const size_t Id, const SDL_Rect & r) : Object(Id, r) {
value = 0.5f;
}
void draw();
void receive(SDL_MouseButtonEvent & mb_event);
SDL_Color innerColor;
float value;
typedef Loki::Functor<void, LOKI_TYPELIST_1(float)> SC_Functor;
SC_Functor changeCB;
};
template <class Child_T, typename V>
struct Number2Status : public Object {
Number2Status(const size_t Id, const SDL_Rect & r, const SDL_Rect & ir, const size_t vId) :
Object(Id, r),
item(r, vId),
number(0), align(0),
innerRect(ir) {}
Child_T item;
V number;
uint8_t align;
SDL_Rect innerRect;
void draw() {
innerRect.x = (align == 0 ? rect.x : rect.x + rect.w - innerRect.w);
innerRect.y = rect.y;
memcpy(&item.rect, &innerRect, sizeof(rect));
for (V k = 0; k < number; k++) {
item.draw();
item.rect.x += (align == 0 ? item.rect.w + 1 : -item.rect.w - 1);
}
if (drawBorder)
draw_border();
}
};
typedef Number2Status<TexturedObject, int32_t> ImageStatusDisplay;
typedef Number2Status<AnimatedTextureObject, int32_t> AnimStatusDisplay;
void screen_gamma_callback(float v);
void create_ingame_gui(bool is32bit);
void update_ingame_gui_values();
void remove_ingame_gui();
static const uint32_t GAMMA_SCROLLBAR_ID = 100;
static const uint32_t GAMMA_LABEL_ID = 101;
static const uint32_t CASH_ID = 200;
static const uint32_t WANTED_LEVEL_ID = 201;
} }
#endif #endif

View File

@ -28,6 +28,9 @@
#include "log.h" #include "log.h"
#include "cistring.h" #include "cistring.h"
#include "opengta.h" #include "opengta.h"
#include "physfsrwops.h"
#include "SDL_image.h"
#include "m_exceptions.h"
namespace ImageUtil { namespace ImageUtil {
using OpenGL::PagedTexture; using OpenGL::PagedTexture;
@ -88,6 +91,7 @@ using OpenGL::PagedTexture;
if (whp.first == 0 || whp.second == 0) { if (whp.first == 0 || whp.second == 0) {
PHYSFS_close(fd); PHYSFS_close(fd);
WARN << "aborting image load" << std::endl; WARN << "aborting image load" << std::endl;
throw E_UNKNOWNKEY(name + " - RAW file size unknown");
} }
Util::BufferCache::LockedBuffer lbuf(nbytes); Util::BufferCache::LockedBuffer lbuf(nbytes);
@ -115,6 +119,7 @@ using OpenGL::PagedTexture;
if (whp.first == 0 || whp.second == 0) { if (whp.first == 0 || whp.second == 0) {
PHYSFS_close(fd); PHYSFS_close(fd);
WARN << "aborting image load" << std::endl; WARN << "aborting image load" << std::endl;
throw E_UNKNOWNKEY(name + " - RAT file size unknown");
} }
Util::BufferCache::LockedBuffer lb1(nbytes); Util::BufferCache::LockedBuffer lb1(nbytes);
PHYSFS_read(fd, lb1(), 1, nbytes); PHYSFS_read(fd, lb1(), 1, nbytes);
@ -131,20 +136,53 @@ using OpenGL::PagedTexture;
return createEmbeddedTexture(whp.first, whp.second, false, lb2()); return createEmbeddedTexture(whp.first, whp.second, false, lb2());
} }
#ifdef WITH_SDL_IMAGE
OpenGL::PagedTexture loadImageSDL(const std::string & name) {
SDL_RWops * rwops = PHYSFSRWOPS_openRead(name.c_str());
SDL_Surface *surface = IMG_Load_RW(rwops, 1);
assert(surface);
NextPowerOfTwo npot(surface->w, surface->h);
uint16_t bpp = surface->format->BytesPerPixel;
uint8_t * buffer = Util::BufferCacheHolder::Instance().requestBuffer(npot.w * npot.h * bpp);
SDL_LockSurface(surface);
copyImage2Image(buffer, (uint8_t*)surface->pixels, surface->pitch, surface->h,
npot.w * bpp);
SDL_UnlockSurface(surface);
SDL_FreeSurface(surface);
GLuint texture = createGLTexture(npot.w, npot.h, (bpp == 4) ? true : false, buffer);
return OpenGL::PagedTexture(texture, 0, 0, GLfloat(surface->w)/npot.w,
GLfloat(surface->h)/npot.h);
}
#endif
GLuint createGLTexture(GLsizei w, GLsizei h, bool rgba, const void* pixels) { GLuint createGLTexture(GLsizei w, GLsizei h, bool rgba, const void* pixels) {
GLuint tex; GLuint tex;
glGenTextures(1, &tex); glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex); glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (!mipmapTextures)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (rgba) if (rgba) {
if (mipmapTextures)
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
//gluBuild2DMipmaps(GL_TEXTURE_2D, 4, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); }
else {
if (mipmapTextures)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixels);
else else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
//gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixels); }
if (supportedMaxAnisoDegree > 1.0f)
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &supportedMaxAnisoDegree);
GL_CHECKERROR; GL_CHECKERROR;
return tex; return tex;
@ -165,13 +203,86 @@ using OpenGL::PagedTexture;
bool rgba, const void* pixels) { bool rgba, const void* pixels) {
NextPowerOfTwo npot(w, h); NextPowerOfTwo npot(w, h);
uint32_t bpp = (rgba ? 4 : 3); uint8_t* buff = (uint8_t*)pixels;
if (!(npot.w == uint32_t(w) && npot.h == uint32_t(h))) {
uint32_t bpp = (rgba ? 4 : 3);
uint32_t bufSize = npot.w * npot.h * bpp; uint32_t bufSize = npot.w * npot.h * bpp;
uint8_t* buff = Util::BufferCacheHolder::Instance().requestBuffer(bufSize); buff = Util::BufferCacheHolder::Instance().requestBuffer(bufSize);
copyImage2Image(buff, (uint8_t*)pixels, w * bpp, h, npot.w * bpp); copyImage2Image(buff, (uint8_t*)pixels, w * bpp, h, npot.w * bpp);
}
GLuint tex = createGLTexture(npot.w, npot.h, rgba, buff); GLuint tex = createGLTexture(npot.w, npot.h, rgba, buff);
return PagedTexture(tex, 0, 0, float(w) / npot.w, float(h) / npot.h); return PagedTexture(tex, 0, 0, float(w) / npot.w, float(h) / npot.h);
} }
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define READINT24(x) ((x)[0]<<16 | (x)[1]<<8 | (x)[2])
#define WRITEINT24(x, i) {(x)[0]=i>>16; (x)[1]=(i>>8)&0xff; x[2]=i&0xff; }
uint8_t* scale2x_24bit(const uint8_t* src, const int src_width, const int src_height) {
const int srcpitch = src_width * 3;
const int dstpitch = src_width * 6;
uint8_t *dstpix = Util::BufferCacheHolder::Instance().requestBuffer(src_width *
src_height * 3 * 4);
int E0, E1, E2, E3, B, D, E, F, H;
for(int looph = 0; looph < src_height; ++looph)
{
for(int loopw = 0; loopw < src_width; ++ loopw)
{
B = READINT24(src + (MAX(0,looph-1)*srcpitch) + (3*loopw));
D = READINT24(src + (looph*srcpitch) + (3*MAX(0,loopw-1)));
E = READINT24(src + (looph*srcpitch) + (3*loopw));
F = READINT24(src + (looph*srcpitch) + (3*MIN(src_width-1,loopw+1)));
H = READINT24(src + (MIN(src_height-1,looph+1)*srcpitch) + (3*loopw));
E0 = D == B && B != F && D != H ? D : E;
E1 = B == F && B != D && F != H ? F : E;
E2 = D == H && D != B && H != F ? D : E;
E3 = H == F && D != H && B != F ? F : E;
WRITEINT24((dstpix + looph*2*dstpitch + loopw*2*3), E0);
WRITEINT24((dstpix + looph*2*dstpitch + (loopw*2+1)*3), E1);
WRITEINT24((dstpix + (looph*2+1)*dstpitch + loopw*2*3), E2);
WRITEINT24((dstpix + (looph*2+1)*dstpitch + (loopw*2+1)*3), E3);
}
}
return dstpix;
}
uint8_t* scale2x_32bit(const uint8_t* src, const int src_width, const int src_height) {
const int srcpitch = src_width * 4;
const int dstpitch = src_width * 8;
uint8_t* dstpix = Util::BufferCacheHolder::Instance().requestBuffer(src_width *
src_height * 4 * 4);
Uint32 E0, E1, E2, E3, B, D, E, F, H;
for(int looph = 0; looph < src_height; ++looph)
{
for(int loopw = 0; loopw < src_width; ++ loopw)
{
B = *(Uint32*)(src + (MAX(0,looph-1)*srcpitch) + (4*loopw));
D = *(Uint32*)(src + (looph*srcpitch) + (4*MAX(0,loopw-1)));
E = *(Uint32*)(src + (looph*srcpitch) + (4*loopw));
F = *(Uint32*)(src + (looph*srcpitch) + (4*MIN(src_width-1,loopw+1)));
H = *(Uint32*)(src + (MIN(src_height-1,looph+1)*srcpitch) + (4*loopw));
E0 = D == B && B != F && D != H ? D : E;
E1 = B == F && B != D && F != H ? F : E;
E2 = D == H && D != B && H != F ? D : E;
E3 = H == F && D != H && B != F ? F : E;
*(Uint32*)(dstpix + looph*2*dstpitch + loopw*2*4) = E0;
*(Uint32*)(dstpix + looph*2*dstpitch + (loopw*2+1)*4) = E1;
*(Uint32*)(dstpix + (looph*2+1)*dstpitch + loopw*2*4) = E2;
*(Uint32*)(dstpix + (looph*2+1)*dstpitch + (loopw*2+1)*4) = E3;
}
}
return dstpix;
}
bool mipmapTextures = false;
GLfloat supportedMaxAnisoDegree = 1.0f;
} }

View File

@ -29,8 +29,8 @@
namespace ImageUtil { namespace ImageUtil {
typedef std::pair<uint16_t, uint16_t> WidthHeightPair; /** Helper to calculate 2^k texture sizes.
*/
struct NextPowerOfTwo { struct NextPowerOfTwo {
NextPowerOfTwo(uint32_t _w, uint32_t _h) { NextPowerOfTwo(uint32_t _w, uint32_t _h) {
w = 1; h = 1; w = 1; h = 1;
@ -41,22 +41,41 @@ namespace ImageUtil {
uint32_t h; uint32_t h;
}; };
/** Run scale2x on 32bit input image.
*
* \note Uses Util::BufferCache for dst memory; lock 'src' before calling
* if it also is a BufferCache buffer.
*/
uint8_t* scale2x_32bit(const uint8_t* src, const int src_width, const int src_height);
uint8_t* scale2x_24bit(const uint8_t* src, const int src_width, const int src_height);
typedef std::pair<uint16_t, uint16_t> WidthHeightPair;
// hardcoded data for known images // hardcoded data for known images
WidthHeightPair lookupImageSize(const std::string & name, const uint32_t size); WidthHeightPair lookupImageSize(const std::string & name, const uint32_t size);
// load a rgb image // load a rgb image
OpenGL::PagedTexture loadImageRAW(const std::string & name); OpenGL::PagedTexture loadImageRAW(const std::string & name);
// load a palette image and guess the palette filename // load a palette image and guess the palette filename
OpenGL::PagedTexture loadImageRAT(const std::string & name); //OpenGL::PagedTexture loadImageRAT(const std::string & name);
// load a palette image using palette file // load a palette image using palette file
OpenGL::PagedTexture loadImageRATWithPalette(const std::string & name, OpenGL::PagedTexture loadImageRATWithPalette(const std::string & name,
const std::string & palette_file); const std::string & palette_file);
// plain simple garden-variety create-a-texture; needs to be ^2 #ifdef WITH_SDL_IMAGE
GLuint createGLTexture(GLsizei w, GLsizei h, bool rgba, const void* pixels); OpenGL::PagedTexture loadImageSDL(const std::string & name);
#endif
// blitting a buffer into another; they should exist! extern bool mipmapTextures;
extern GLfloat supportedMaxAnisoDegree;
// plain simple garden-variety create-a-texture; needs to be 2^k
GLuint createGLTexture(GLsizei w, GLsizei h, bool rgba,
const void* pixels);
// blitting a buffer into another; no checks done!
void copyImage2Image(uint8_t *dest, const uint8_t *src, const uint16_t void copyImage2Image(uint8_t *dest, const uint8_t *src, const uint16_t
srcWidth, const uint16_t srcHeight, const uint16_t destWidth); srcWidth, const uint16_t srcHeight, const uint16_t destWidth);
// texture-class instance from pixel data; does transform to 2^k if required
OpenGL::PagedTexture createEmbeddedTexture(GLsizei w, GLsizei h, bool rgba, OpenGL::PagedTexture createEmbeddedTexture(GLsizei w, GLsizei h, bool rgba,
const void *pixels); const void *pixels);
} }

68
util/key_handler.cpp Normal file
View File

@ -0,0 +1,68 @@
/************************************************************************
* Copyright (c) 2005-2007 tok@openlinux.org.uk *
* *
* This software is provided as-is, without any express or implied *
* warranty. In no event will the authors be held liable for any *
* damages arising from the use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute *
* it freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must *
* not claim that you wrote the original software. If you use this *
* software in a product, an acknowledgment in the product documentation *
* would be appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must *
* not be misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source *
* distribution. *
************************************************************************/
#include <SDL_keysym.h>
#include "key_handler.h"
#include "log.h"
namespace Util {
bool IngameCommonKeys::up(const uint32_t & key) {
bool handled = false;
return handled;
}
bool IngameCommonKeys::down(const uint32_t & key) {
return false;
}
void KeyHandlerChain::up(const uint32_t & key) {
for (ListOfHandlers::iterator i = activeHandlers.begin();
i != activeHandlers.end(); i++) {
if ((*i)->up(key))
return;
}
}
void KeyHandlerChain::down(const uint32_t & key) {
for (ListOfHandlers::iterator i = activeHandlers.begin();
i != activeHandlers.end(); i++) {
if ((*i)->down(key))
return;
}
}
void KeyHandlerChain::addHandler(KeyHandler * kh, bool front) {
if (front)
activeHandlers.push_front(kh);
else
activeHandlers.push_back(kh);
}
void KeyHandlerChain::removeHandler(KeyHandler * kh) {
for (ListOfHandlers::iterator i = activeHandlers.begin();
i != activeHandlers.end(); i++) {
if (kh == *i)
activeHandlers.erase(i);
}
ERROR << "not a valid handler pointer" << std::endl;
}
}

86
util/key_handler.h Normal file
View File

@ -0,0 +1,86 @@
/************************************************************************
* Copyright (c) 2005-2007 tok@openlinux.org.uk *
* *
* This software is provided as-is, without any express or implied *
* warranty. In no event will the authors be held liable for any *
* damages arising from the use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute *
* it freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must *
* not claim that you wrote the original software. If you use this *
* software in a product, an acknowledgment in the product documentation *
* would be appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must *
* not be misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source *
* distribution. *
************************************************************************/
#ifndef UTIL_KEYHANDLER_H
#define UTIL_KEYHANDLER_H
#include <stdint.h>
#include <list>
#include <vector>
#include "pf_tree.hpp"
namespace Util {
/** Interface for key listeners.
*
* Must implement both keypress and release functions;
* the functions should return \em true when the input
* value is consumed by a handler.
*/
class KeyHandler {
public:
virtual ~KeyHandler() {}
virtual bool up(const uint32_t & key) = 0;
virtual bool down(const uint32_t & key) = 0;
};
/** Keys that do _not_ control the player character.
*/
class IngameCommonKeys : public KeyHandler {
public:
bool up(const uint32_t & key);
bool down(const uint32_t & key);
};
class MenuKeys : public KeyHandler {
public:
bool up(const uint32_t & key);
bool down(const uint32_t & key);
};
class CheatKeys : public KeyHandler {
public:
bool up(const uint32_t & key);
bool down(const uint32_t & key);
template <typename T>
struct Callback_Lua {
void call(T);
};
typedef PrefixFreeTree::Walker<uint32_t, Callback_Lua> TreeOfCheats;
private:
std::vector<uint32_t> cheat_fn_refs;
};
class KeyHandlerChain {
public:
void up(const uint32_t & key);
void down(const uint32_t & key);
void addHandler(KeyHandler*, bool front = true);
void removeHandler(KeyHandler*);
private:
typedef std::list<KeyHandler*> ListOfHandlers;
ListOfHandlers activeHandlers;
};
}
#endif

View File

@ -12,17 +12,58 @@
#define ERROR_AND_EXIT(ec) error_code = ec; exit(ec); #define ERROR_AND_EXIT(ec) error_code = ec; exit(ec);
#define GL_CHECKERROR { int _err = glGetError(); if (_err != GL_NO_ERROR) \ #define GL_CHECKERROR { int _err = glGetError(); if (_err != GL_NO_ERROR) \
Util::Log::error(__FILE__, __LINE__) << "GL error: " << _err << " = " << Util::Log::glErrorName(_err) << std::endl; } Util::Log::error(__FILE__, __LINE__) << "GL error: " << _err << " = " << Util::Log::glErrorName(_err) << std::endl; }
#define ANSI_COLOR_OFF "\033[0m"
#define ANSI_COLOR_INFO "\033[32mInfo ("
#define ANSI_COLOR_WARN "\033[33mWarning ("
#define ANSI_COLOR_ERR "\033[31mError ("
namespace Util { namespace Util {
class Log { class Log {
public: public:
inline static std::ostream & info(const char* f, int l) { inline static std::ostream & info(const char* f, int l) {
if (level) return emptyStream; std::cout << "Info (" << f << ":" << l << "): "; return std::cout; if (level) return emptyStream;
#ifdef LOG_USE_ANSI_COLORS
std::cout << ANSI_COLOR_INFO <<
#else
std::cout << "Info (" <<
#endif
f << ":" << l << "): "
#ifdef LOG_USE_ANSI_COLORS
<< ANSI_COLOR_OFF;
#else
;
#endif
return std::cout;
} }
inline static std::ostream & warn(const char* f, int l) { inline static std::ostream & warn(const char* f, int l) {
if (level > 1) return emptyStream; std::cerr << "Warning (" << f << ":" << l << "): "; return std::cerr; if (level > 1) return emptyStream;
#ifdef LOG_USE_ANSI_COLORS
std::cerr << ANSI_COLOR_WARN <<
#else
std::cerr << "Warning (" <<
#endif
f << ":" << l << "): "
#ifdef LOG_USE_ANSI_COLORS
<< ANSI_COLOR_OFF;
#else
;
#endif
return std::cerr;
} }
inline static std::ostream & error(const char* f, int l) { inline static std::ostream & error(const char* f, int l) {
std::cerr << "Error ("<< f << ":" << l << "): "; return std::cerr; #ifdef LOG_USE_ANSI_COLORS
std::cerr << ANSI_COLOR_ERR <<
#else
std::cerr << "Error (" <<
#endif
f << ":" << l << "): "
#ifdef LOG_USE_ANSI_COLORS
<< ANSI_COLOR_OFF;
#else
;
#endif
return std::cerr;
} }
static void setOutputLevel(unsigned int newLevel); static void setOutputLevel(unsigned int newLevel);
static const char* glErrorName(int k); static const char* glErrorName(int k);

View File

@ -4,6 +4,22 @@
namespace Util { namespace Util {
void SpriteCreationArea::setRects(const SDL_Rect & allowed, const SDL_Rect & denied) { void SpriteCreationArea::setRects(const SDL_Rect & allowed, const SDL_Rect & denied) {
validRects = std::make_pair<SDL_Rect, SDL_Rect>(allowed, denied); validRects = std::make_pair<SDL_Rect, SDL_Rect>(allowed, denied);
onScreen = denied;
}
bool SpriteCreationArea::isOnScreen(const Vector3D & p) {
/* INFO << p.x << " " << p.y << " " << p.z << std::endl;
INFO << onScreen.x <<", " << onScreen.y << " -> " <<
onScreen.x + onScreen.w << ", " << onScreen.y + onScreen.h << std::endl;
*/
if ((p.x >= onScreen.x) && (p.x <= onScreen.x + onScreen.w) &&
(p.z >= onScreen.y) && (p.z <= onScreen.y + onScreen.h))
return true;
return false;
}
bool SpriteCreationArea::isOffScreen(const Vector3D & p) {
return false;
} }
TupleOfUint8 SpriteCreationArea::getValidCoord() { TupleOfUint8 SpriteCreationArea::getValidCoord() {
@ -11,4 +27,29 @@ namespace Util {
uint32_t y = rnd.nextUint(validRects.first.h) + validRects.first.y; uint32_t y = rnd.nextUint(validRects.first.h) + validRects.first.y;
return std::make_pair<uint8_t, uint8_t>(x, y); return std::make_pair<uint8_t, uint8_t>(x, y);
} }
int item_count(MapOfPair2Int & m, int a, int b) {
MapOfPair2Int::iterator j = m.find( std::make_pair<int, int>(a, b) );
if (j == m.end())
return 0;
return j->second;
}
void register_item1(MapOfPair2Int & m, int a, int b) {
m.insert( std::make_pair< Pair2Int, int>(
std::make_pair<int, int>(a, b),
1)
);
}
void register_item(MapOfPair2Int & m, int a, int b) {
Pair2Int _p(std::make_pair<int, int>(a, b));
MapOfPair2Int::iterator j = m.find(_p);
if (j == m.end())
register_item1(m, a, b);
else
j->second++;
}
} }

View File

@ -2,7 +2,10 @@
#define MAP_HELPER_H #define MAP_HELPER_H
#include <list> #include <list>
#include <map>
#include <SDL_video.h> #include <SDL_video.h>
#include <cassert> // yasli/random.h needs it
#include "math3d.h"
#include "yasli/random.h" #include "yasli/random.h"
namespace Util { namespace Util {
@ -17,6 +20,42 @@ namespace Util {
void setRects(const SDL_Rect & allowed, const SDL_Rect & denied); void setRects(const SDL_Rect & allowed, const SDL_Rect & denied);
TupleOfUint8 getValidCoord(); TupleOfUint8 getValidCoord();
Random rnd; Random rnd;
bool isOnScreen(const Vector3D & p);
bool isOffScreen(const Vector3D & p);
private:
SDL_Rect onScreen;
}; };
/** lesser than comparison of two std::pair<int, int>.
*/
template <typename T>
struct lt_pair {
bool operator() (const T & a, const T & b) {
if (a.first < b.first)
return true;
if (a.first > b.first)
return false;
return (a.second < b.second);
}
};
typedef std::pair<int, int> Pair2Int;
typedef lt_pair<std::pair<int, int> > cmp_Pair2Int;
typedef std::map<Pair2Int, int, cmp_Pair2Int> MapOfPair2Int;
/** count of Pair2Int(a,b) in the map.
* @return 0 if no entry at that \e position
* @return count otherwise
*/
int item_count(MapOfPair2Int & m, int a, int b);
/** insert (may overwrite) count 1 at Pair2Int(a, b).
*/
void register_item1(MapOfPair2Int & m, int a, int b);
/** register and count Pair2Int(a, b).
*/
void register_item(MapOfPair2Int & m, int a, int b);
} }
#endif #endif

96
util/pf_tree.cpp Normal file
View File

@ -0,0 +1,96 @@
/************************************************************************
* Copyright (c) 2005-2007 tok@openlinux.org.uk *
* *
* This software is provided as-is, without any express or implied *
* warranty. In no event will the authors be held liable for any *
* damages arising from the use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute *
* it freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must *
* not claim that you wrote the original software. If you use this *
* software in a product, an acknowledgment in the product documentation *
* would be appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must *
* not be misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source *
* distribution. *
************************************************************************/
#include "pf_tree.hpp"
namespace PrefixFreeTree {
Node::~Node() {
for (MapType::iterator i = map.begin(); i != map.end(); i++) {
delete i->second;
}
map.clear();
}
Node & Node::insert(const char * str, size_t offset) {
size_t str_len = strlen(str);
if (offset < str_len) {
value_t node_val = str[offset];
MapType::iterator i = map.find(node_val);
offset++;
if (i == map.end()) {
map[node_val] = new Node();
return map[node_val]->insert(str, offset);
}
else {
if (i->second->isLeaf()) {
std::ostringstream os;
os << "Cannot enter '" << str << "' at offset " << offset <<
" as a leaf node already exists";
throw E_INVALIDFORMAT(os.str());
}
if ((offset == str_len) && (!i->second->isLeaf())) {
std::ostringstream os;
os << "Cannot enter '" << str
<< "' as a non-leaf node already exists" << std::endl;
throw E_INVALIDFORMAT(os.str());
}
return i->second->insert(str, offset);
}
}
return *this;
}
}
#ifdef SIMPLE_TREE_DEMO
#include <iostream>
template <typename T>
struct Echo {
void call(T t) {
std::cout << "Echo: " << t << std::endl;
}
};
using namespace std;
int main(int argc, char* argv[]) {
PrefixFreeTree::Walker<uint32_t, Echo> m;
uint32_t i = 1;
while (!cin.eof()) {
std::string inputs;
cin >> inputs;
if (inputs.size()) {
std::cout << "-" << inputs << "-" << std::endl;
PrefixFreeTree::Node & n = m.insert(inputs.c_str());
n.leaf_value = i;
i++;
}
}
const char* input = argv[1];
int len = strlen(input);
for (int i = 0; i < len; i++) {
m.push(input[i]);
}
}
#endif

75
util/pf_tree.hpp Normal file
View File

@ -0,0 +1,75 @@
/************************************************************************
* Copyright (c) 2005-2007 tok@openlinux.org.uk *
* *
* This software is provided as-is, without any express or implied *
* warranty. In no event will the authors be held liable for any *
* damages arising from the use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute *
* it freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must *
* not claim that you wrote the original software. If you use this *
* software in a product, an acknowledgment in the product documentation *
* would be appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must *
* not be misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source *
* distribution. *
************************************************************************/
#ifndef PREFIX_FREE_TREE_H
#define PREFIX_FREE_TREE_H
#include <string.h>
#include <map>
#include <string>
#include <sstream>
#include "m_exceptions.h"
namespace PrefixFreeTree {
struct Node {
~Node();
typedef int value_t;
uint32_t leaf_value;
typedef std::map<value_t, Node* > MapType;
MapType map;
bool isLeaf() const { return (map.size() == 0); }
Node & insert(const char * str, size_t offset = 0);
};
#define CHECK_HANDLE_LEAF if (curPos->isLeaf()) { Handler<T>::call(curPos->leaf_value); }
template <typename T, template <class> class Handler>
class Walker : public Handler<T>, public Node {
public:
Walker() : Handler<T>(), Node(), curPos(this) {}
void push(int v) {
MapType::iterator i = curPos->map.find(v);
if (i != curPos->map.end()) {
curPos = i->second;
CHECK_HANDLE_LEAF;
}
else {
i = map.find(v);
if (i != map.end()) {
curPos = i->second;
CHECK_HANDLE_LEAF;
}
else
curPos = this;
}
}
private:
Node * curPos;
};
}
#undef CHECK_HANDLE_LEAF
#endif

View File

@ -46,7 +46,12 @@ namespace Audio {
OpenGTA::SoundsDB::Entry & e = db.getEntry(idx); OpenGTA::SoundsDB::Entry & e = db.getEntry(idx);
size_t si; size_t si;
unsigned char* mem = db.getBuffered(idx); unsigned char* mem = db.getBuffered(idx);
Uint8 *mem2 = (Uint8*)Audio::resample_new(mem, e.rawSize, si, e.sampleRate, 44100); Uint8 *mem2 = NULL;
if (file.find("000") != std::string::npos) {
mem2 = (Uint8*)Audio::resample16(mem, e.rawSize, si, e.sampleRate, 44100);
}
else
mem2 = (Uint8*)Audio::resample_new(mem, e.rawSize, si, e.sampleRate, 44100);
Mix_Chunk * music = Mix_QuickLoad_RAW(mem2, si); Mix_Chunk * music = Mix_QuickLoad_RAW(mem2, si);
return ChunkData(mem2, music, 1); return ChunkData(mem2, music, 1);
} }

View File

@ -20,6 +20,7 @@
* 3. This notice may not be removed or altered from any source * * 3. This notice may not be removed or altered from any source *
* distribution. * * distribution. *
************************************************************************/ ************************************************************************/
#include <iostream>
#include "sound_resample2.h" #include "sound_resample2.h"
#include "interpolate.hpp" #include "interpolate.hpp"
@ -89,4 +90,58 @@ namespace Audio {
while (src < src_end); while (src < src_end);
return stereo_data; return stereo_data;
} }
Sint16 *resample16 (Uint8 * src, size_t sourcelen, size_t & size,
int rate, int wanted_rate) {
int fp_pos = 0;
int fp_speed = (1 << 16) * rate / wanted_rate;
size = sourcelen;
while (size & 0xFFFF0000)
size >>= 1, rate = (rate >> 1) + 1;
size = (size * wanted_rate / rate) << 1;
Sint16 *stereo_data = new Sint16[size];
Sint16 *data = stereo_data;
Uint8 *src_end = src + sourcelen;
int result;
int a = *(src + 0);
a = a + (*(src + 1) << 8);
int b = *(src + 2);
b = b + (*(src + 3) << 8);
int c = *(src + 4);
c = c + (*(src + 5) << 8);
std::cout << a << " " << b << " " << c << std::endl;
Math::Interpolator::Cubic<float> inter(a * 0.8333f, b * 0.8333f, c * 0.8333f);
do
{
do
{
result = int(inter.getAt(fp_pos / float(0x0000FFFF)));
if (result < -32768)
result = -32768;
else if (result > 32767)
result = 32767;
*data++ = result;
fp_pos += fp_speed;
}
while (!(fp_pos & 0xFFFF0000));
src++;
fp_pos &= 0x0000FFFF;
if (src + 2 < src_end)
{
c = *(src + 2);
c = c + (*(src + 3) << 8);
inter.shiftAndFeed (c * 0.8333f);
}
else
inter.shift ();
}
while (src < src_end);
return stereo_data;
}
} }

View File

@ -28,7 +28,7 @@ namespace Audio
{ {
Sint16 *resample_new (Uint8 * sourcedata, size_t sourcelen, Sint16 *resample_new (Uint8 * sourcedata, size_t sourcelen,
size_t & destlen, int current_rate, int wanted_rate); size_t & destlen, int current_rate, int wanted_rate);
Sint16 *resample_new_mono (Uint8 * sourcedata, size_t sourcelen, Sint16 *resample16 (Uint8 * sourcedata, size_t sourcelen,
size_t & destlen, int current_rate, size_t & destlen, int current_rate,
int wanted_rate); int wanted_rate);
} }

View File

@ -1,6 +1,7 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include "sound_system.h" #include "sound_system.h"
#include "sound_music_player.h"
#include "physfsrwops.h" #include "physfsrwops.h"
#include "m_exceptions.h" #include "m_exceptions.h"
#include "log.h" #include "log.h"
@ -10,7 +11,12 @@ namespace Audio {
#ifdef WITH_SOUND #ifdef WITH_SOUND
SoundSystem::SoundSystem() : device(), chunkCache() { SoundSystem::SoundSystem() : device(), chunkCache() {
SDL_InitSubSystem(SDL_INIT_AUDIO); SDL_InitSubSystem(SDL_INIT_AUDIO);
try {
device.open(); device.open();
}
catch (const Exception & e) {
ERROR << e.what() << std::endl;
}
enabled = true; enabled = true;
if (device.getStatus() == SoundDevice::OPEN) if (device.getStatus() == SoundDevice::OPEN)
Sound_Init(); Sound_Init();
@ -59,6 +65,8 @@ namespace Audio {
} }
void SoundSystem::listMusicDecoders() { void SoundSystem::listMusicDecoders() {
if (!enabled)
return;
std::cout << "* Supported music decoders *" << std::endl; std::cout << "* Supported music decoders *" << std::endl;
const Sound_DecoderInfo **i; const Sound_DecoderInfo **i;
for (i = Sound_AvailableDecoders(); *i != NULL; i++) { for (i = Sound_AvailableDecoders(); *i != NULL; i++) {
@ -91,7 +99,13 @@ int main(int argc, char* argv[]) {
SoundSystem noisemaker; SoundSystem noisemaker;
noisemaker.listMusicDecoders(); noisemaker.listMusicDecoders();
if (argc == 2)
noisemaker.playMusic(argv[1]); noisemaker.playMusic(argv[1]);
if (argc == 3) {
noisemaker.playFx(argv[1], atoi(argv[2]));
while (Mix_Playing(-1))
SDL_Delay(500);
}
MusicPlayerCtrl::musicFinishedCB = CB_MusicDone; MusicPlayerCtrl::musicFinishedCB = CB_MusicDone;
while (MusicPlayerCtrl::isPlaying) { while (MusicPlayerCtrl::isPlaying) {
SDL_Delay(1000); SDL_Delay(1000);

View File

@ -18,8 +18,8 @@ namespace Audio {
SoundSystem(); SoundSystem();
~SoundSystem(); ~SoundSystem();
void playFx(std::string file, size_t idx); void playFx(std::string file, size_t idx);
void SoundSystem::playMusic(std::string file); void playMusic(std::string file);
void SoundSystem::listMusicDecoders(); void listMusicDecoders();
bool enabled; bool enabled;
}; };
} }

View File

@ -42,10 +42,15 @@
#include "navdata.h" #include "navdata.h"
#include "opengta.h" #include "opengta.h"
#include "spritemanager.h" #include "spritemanager.h"
#include "gl_spritecache.h"
#include "timer.h" #include "timer.h"
#ifdef WITH_LUA #ifdef WITH_LUA
#include "lua_addon/lua_vm.h" #include "lua_addon/lua_vm.h"
#include "lua_addon/lua_stackguard.h"
#endif #endif
#include "gui.h"
#include "font_cache.h"
#include "ai.h"
#define getPedById getPed #define getPedById getPed
#define removePedById removePed #define removePedById removePed
@ -54,10 +59,12 @@
extern SDL_Surface* screen; extern SDL_Surface* screen;
extern int global_EC; extern int global_EC;
extern int global_Done; extern int global_Done;
extern int global_Restart;
GLfloat mapPos[3] = {12.0f, 12.0f, 20.0f}; GLfloat mapPos[3] = {12.0f, 12.0f, 20.0f};
OpenGTA::CityView *city = NULL; OpenGTA::CityView *city = NULL;
OpenGL::DrawableFont* m_font = NULL; //OpenGL::DrawableFont* m_font = NULL;
GUI::Label * fps_label = NULL;
int city_num = 0; int city_num = 0;
const char* styles_8[3] = { "STYLE001.GRY", "STYLE002.GRY", "STYLE003.GRY" }; const char* styles_8[3] = { "STYLE001.GRY", "STYLE002.GRY", "STYLE003.GRY" };
@ -81,6 +88,11 @@ int ped_anim = 0;
int bbox_toggle = 0; int bbox_toggle = 0;
int texsprite_toggle = 0; int texsprite_toggle = 0;
int follow_toggle = 0; int follow_toggle = 0;
float anisotropic_filter_degree = 2.0f;
int mipmap_textures = -1;
int vsync_config = -1;
int city_blocks_area = -1;
int config_scale2x = 1;
OpenGTA::SpriteObject::Animation pedAnim(0, 0); OpenGTA::SpriteObject::Animation pedAnim(0, 0);
#ifdef OGTA_DEFAULT_GRAPHICS_G24 #ifdef OGTA_DEFAULT_GRAPHICS_G24
bool highcolor_data = true; bool highcolor_data = true;
@ -93,6 +105,10 @@ bool player_toggle_run = false;
const char* script_file = NULL; const char* script_file = NULL;
int paused = 0; int paused = 0;
int next_station_zoom = 0; int next_station_zoom = 0;
bool gamma_slide = false;
float screen_gamma = 1.0f;
Vector3D test_dot(-1, -1, -1);
/* /*
void ERROR(const char* s) { void ERROR(const char* s) {
@ -106,8 +122,8 @@ void on_exit() {
SDL_Quit(); SDL_Quit();
if (city) if (city)
delete city; delete city;
if (m_font) //if (m_font)
delete m_font; // delete m_font;
PHYSFS_deinit(); PHYSFS_deinit();
if (global_EC) if (global_EC)
std::cerr << "Exiting after fatal problem - please see output above" << std::endl; std::cerr << "Exiting after fatal problem - please see output above" << std::endl;
@ -123,6 +139,17 @@ void print_usage(const char* argv0) {
" -c k : 0 = 8bit GRY, 1 = 24bit G24" << std::endl << " -c k : 0 = 8bit GRY, 1 = 24bit G24" << std::endl <<
" -f : fullscreen on program-start" << std::endl << " -f : fullscreen on program-start" << std::endl <<
" -V : show version & compile-time switches" << std::endl << " -V : show version & compile-time switches" << std::endl <<
" -M k : texture mipmaps: 0 = disable, 1 = enable" << std::endl <<
" -x k : scale2x sprites: 0 = disable, 1 = enable" << std::endl <<
" -v k : vertical sync: 0 = disable, 1 = try with SDL" <<
#ifdef LINUX
", 2 = try with GLX" <<
#elif WIN32
", 2 = try with GLW" <<
#endif
std::endl <<
" -a f : anisotropic texture filtering degree: 1.0 = disabled"
<< std::endl <<
std::endl << std::endl <<
" -m map_file -g style_file : load specified files" << std::endl << " -m map_file -g style_file : load specified files" << std::endl <<
" -w width -h height : screen dimension" << std::endl << " -w width -h height : screen dimension" << std::endl <<
@ -132,12 +159,13 @@ void print_usage(const char* argv0) {
"The following environment variables are used when defined:" << std::endl << "The following environment variables are used when defined:" << std::endl <<
" OGTA_DATA : PhysicsFS source for main data file lookup" << std::endl << " OGTA_DATA : PhysicsFS source for main data file lookup" << std::endl <<
" OGTA_HOME : unused - will be config/save dir" << std::endl << " OGTA_HOME : unused - will be config/save dir" << std::endl <<
" OGTA_MOD : PhysicsFS source to override main data files" << std::endl; " OGTA_MOD : PhysicsFS source to override main data files" << std::endl <<
" OGTA_LANG : defines the fxt language file to load" << std::endl;
} }
void print_version_info() { void print_version_info() {
#define PRINT_FORMATED(spaces) std::setw(spaces) << std::left << #define PRINT_FORMATED(spaces) std::setw(spaces) << std::left <<
#define PRINT_OFFSET PRINT_FORMATED(18) #define PRINT_OFFSET PRINT_FORMATED(19)
std::cout << PRINT_OFFSET "OpenGTA version:" << OGTA_VERSION_INFO << std::endl << std::cout << PRINT_OFFSET "OpenGTA version:" << OGTA_VERSION_INFO << std::endl <<
PRINT_OFFSET "platform:" << OGTA_PLATFORM_INFO << std::endl << PRINT_OFFSET "platform:" << OGTA_PLATFORM_INFO << std::endl <<
@ -155,11 +183,26 @@ void print_version_info() {
"no" << "no" <<
#endif #endif
std::endl << std::endl <<
PRINT_OFFSET "SDL_image support:" <<
#ifdef WITH_SDL_IMAGE
"yes" <<
#else
"no" <<
#endif
std::endl <<
PRINT_OFFSET "vsync support:" << PRINT_OFFSET "vsync support:" <<
#ifdef HAVE_SDL_VSYNC #ifdef HAVE_SDL_VSYNC
"yes" << "yes" <<
#else #else
"no" << "no" <<
#endif
std::endl <<
PRINT_OFFSET "scale2x support:" <<
#ifdef DO_SCALE2X
"yes" <<
#else
"no" <<
#endif #endif
std::endl << std::endl <<
@ -188,24 +231,30 @@ void parse_args(int argc, char* argv[]) {
opterr = 0; opterr = 0;
#ifdef WITH_LUA #ifdef WITH_LUA
#define VIEWER_FLAGS "s:w:h:c:m:g:l:fV" #define VIEWER_FLAGS "a:s:w:h:c:m:M:g:l:v:x:fV"
#else #else
#define VIEWER_FLAGS "w:h:c:m:g:l:fV" #define VIEWER_FLAGS "a:w:h:c:m:M:g:l:v:x:fV"
#endif #endif
while ((c = getopt (argc, argv, VIEWER_FLAGS)) != -1) while ((c = getopt (argc, argv, VIEWER_FLAGS)) != -1)
switch (c) switch (c)
{ {
#ifdef WITH_LUA #ifdef WITH_LUA
case 's': case 's':
script_file = std::string(optarg); script_file = optarg;
break; break;
#endif #endif
case 'a':
anisotropic_filter_degree = atof(optarg);
break;
case 'c': case 'c':
highcolor_data = atoi(optarg); highcolor_data = atoi(optarg);
break; break;
case 'm': case 'm':
specific_map = std::string(optarg); specific_map = std::string(optarg);
break; break;
case 'M':
mipmap_textures = atoi(optarg);
break;
case 'g': case 'g':
specific_style = std::string(optarg); specific_style = std::string(optarg);
break; break;
@ -221,10 +270,16 @@ void parse_args(int argc, char* argv[]) {
case 'f': case 'f':
full_screen = true; full_screen = true;
break; break;
case 'v':
vsync_config = atoi(optarg);
break;
case 'V': case 'V':
print_version_info(); print_version_info();
exit(0); exit(0);
break; break;
case 'x':
config_scale2x = atoi(optarg);
break;
default: default:
if (optopt == '?') { if (optopt == '?') {
print_usage(argv[0]); print_usage(argv[0]);
@ -254,7 +309,7 @@ void run_init(const char* prg_name) {
// physfs-ogta // physfs-ogta
Util::FileHelper & fh = GET_FILE_HELPER; Util::FileHelper & fh = GET_FILE_HELPER;
if (fh.existsInSystemFS(fh.getBaseDataPath())) { if (fh.existsInSystemFS(fh.getBaseDataPath())) {
PHYSFS_addToSearchPath(GET_FILE_HELPER.getBaseDataPath().c_str(), 1); PHYSFS_addToSearchPath(fh.getBaseDataPath().c_str(), 1);
} }
else { else {
WARN << "Could not load data-source: " << fh.getBaseDataPath() << std::endl; WARN << "Could not load data-source: " << fh.getBaseDataPath() << std::endl;
@ -263,10 +318,12 @@ void run_init(const char* prg_name) {
PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1); PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1);
if (fh.existsInSystemFS(fh.getModDataPath())) if (fh.existsInSystemFS(fh.getModDataPath()))
PHYSFS_addToSearchPath(GET_FILE_HELPER.getModDataPath().c_str(), 0); PHYSFS_addToSearchPath(fh.getModDataPath().c_str(), 0);
// screen, no window yet
OpenGL::Screen & screen = OpenGL::ScreenHolder::Instance(); OpenGL::Screen & screen = OpenGL::ScreenHolder::Instance();
// check for a configfile
#ifdef WITH_LUA #ifdef WITH_LUA
if (fh.existsInVFS("config")) { if (fh.existsInVFS("config")) {
char* config_as_string = (char*)fh.bufferFromVFS( char* config_as_string = (char*)fh.bufferFromVFS(
@ -274,7 +331,17 @@ void run_init(const char* prg_name) {
OpenGTA::Script::LuaVM & vm = OpenGTA::Script::LuaVMHolder::Instance(); OpenGTA::Script::LuaVM & vm = OpenGTA::Script::LuaVMHolder::Instance();
try { try {
vm.runString(config_as_string); //vm.runString(config_as_string);
lua_State *L = vm.getInternalState();
Util::LGUARD(L);
if (luaL_loadbuffer(L, config_as_string, strlen(config_as_string), "config"))
throw E_SCRIPTERROR("Error running string: " + std::string(lua_tostring(L, -1)));
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setglobal(L, "config");
lua_setfenv(L, -2);
if (lua_pcall(L, 0, 0, 0))
throw E_SCRIPTERROR("Error running string: " + std::string(lua_tostring(L, -1)));
} }
catch (const Util::ScriptError & e) { catch (const Util::ScriptError & e) {
std::cerr << "Error in config-file: " << e.what() << std::endl; std::cerr << "Error in config-file: " << e.what() << std::endl;
@ -282,20 +349,33 @@ void run_init(const char* prg_name) {
exit(1); exit(1);
} }
lua_State *L = vm.getInternalState();
lua_getglobal(L, "config");
if (lua_type(L, 1) == LUA_TTABLE) {
try { try {
Uint32 sw = vm.getGlobalInt("screen_width"); bool sh = vm.getBool("use_g24_graphics");
highcolor_data = sh;
}
catch (const Util::ScriptError & e) {}
try {
Uint32 sw = vm.getInt("screen_width");
if (!arg_screen_w) if (!arg_screen_w)
arg_screen_w = sw; arg_screen_w = sw;
} }
catch (const Util::ScriptError & e) {} catch (const Util::ScriptError & e) {}
try { try {
Uint32 sh = vm.getGlobalInt("screen_height"); Uint32 sh = vm.getInt("screen_height");
if (!arg_screen_h) if (!arg_screen_h)
arg_screen_h = sh; arg_screen_h = sh;
} }
catch (const Util::ScriptError & e) {} catch (const Util::ScriptError & e) {}
try { try {
Uint32 sh = vm.getGlobalInt("full_screen"); int sh = vm.getInt("screen_vsync");
screen.setupVsync(sh);
}
catch (const Util::ScriptError & e) {}
try {
bool sh = vm.getBool("full_screen");
if (!full_screen) if (!full_screen)
full_screen = sh; full_screen = sh;
} }
@ -305,31 +385,111 @@ void run_init(const char* prg_name) {
float np = screen.getNearPlane(); float np = screen.getNearPlane();
float fp = screen.getFarPlane(); float fp = screen.getFarPlane();
try { try {
fov = vm.getGlobalFloat("field_of_view"); fov = vm.getFloat("gl_field_of_view");
} }
catch (const Util::ScriptError & e) {} catch (const Util::ScriptError & e) {}
try { try {
np = vm.getGlobalFloat("near_plane"); np = vm.getFloat("gl_near_plane");
} }
catch (const Util::ScriptError & e) {} catch (const Util::ScriptError & e) {}
try { try {
fp = vm.getGlobalFloat("far_plane"); fp = vm.getFloat("gl_far_plane");
} }
catch (const Util::ScriptError & e) {} catch (const Util::ScriptError & e) {}
screen.setupGlVars(fov, np, fp); screen.setupGlVars(fov, np, fp);
try {
bool sh = vm.getBool("gl_mipmap_textures");
ImageUtil::mipmapTextures = sh;
}
catch (const Util::ScriptError & e) {}
try {
bool sh = vm.getBool("scale2x_sprites");
OpenGL::SpriteCacheHolder::Instance().setScale2x(sh);
}
catch (const Util::ScriptError & e) {}
try {
int sh = vm.getInt("active_area_size");
city_blocks_area = sh;
}
catch (const Util::ScriptError & e) {}
}
// can't check for gl-extensions now
} }
#endif #endif
//INFO << "AREA:: " << city_blocks_area << std::endl;
// check both width & height defined
if ((arg_screen_h && !arg_screen_w) || (!arg_screen_h && arg_screen_w)) { if ((arg_screen_h && !arg_screen_w) || (!arg_screen_h && arg_screen_w)) {
WARN << "Invalid screen specified: " << arg_screen_w << "x" << WARN << "Invalid screen specified: " << arg_screen_w << "x" <<
arg_screen_h << " - using default" << std::endl; arg_screen_h << " - using default" << std::endl;
arg_screen_h = 0; arg_screen_w = 0; arg_screen_h = 0; arg_screen_w = 0;
} }
// fullscreen before first video init; only chance to set it on win32
screen.setFullScreenFlag(full_screen); screen.setFullScreenFlag(full_screen);
if (vsync_config != -1)
screen.setupVsync(vsync_config);
// create screen
screen.activate(arg_screen_w, arg_screen_h); screen.activate(arg_screen_w, arg_screen_h);
SDL_EnableKeyRepeat( 100, SDL_DEFAULT_REPEAT_INTERVAL );
SDL_EnableKeyRepeat( 0, 0 );
//SDL_EnableKeyRepeat( 100, SDL_DEFAULT_REPEAT_INTERVAL );
// more setup; that requires an active screen
#ifdef WITH_LUA
OpenGTA::Script::LuaVM & vm = OpenGTA::Script::LuaVMHolder::Instance();
lua_State *L = vm.getInternalState();
if (lua_type(L, 1) == LUA_TTABLE) {
try {
float v = vm.getFloat("gl_anisotropic_textures");
if (ImageUtil::supportedMaxAnisoDegree >= v)
ImageUtil::supportedMaxAnisoDegree = v;
}
catch (const Util::ScriptError & e) {}
try {
float v = (highcolor_data ? vm.getFloat("screen_gamma_g24") :
vm.getFloat("screen_gamma_gry"));
screen_gamma = v;
SDL_SetGamma(v, v, v);
}
catch (const Util::ScriptError & e) {}
}
lua_settop(L, 0);
#endif
if (ImageUtil::supportedMaxAnisoDegree >= anisotropic_filter_degree)
ImageUtil::supportedMaxAnisoDegree = anisotropic_filter_degree;
else
WARN << "Using filter degree " << ImageUtil::supportedMaxAnisoDegree <<
", requested " << anisotropic_filter_degree << " not supported" << std::endl;
switch(mipmap_textures) {
case -1:
break;
case 0:
ImageUtil::mipmapTextures = false;
break;
default:
ImageUtil::mipmapTextures = true;
break;
}
// before any graphics are loaded
OpenGL::SpriteCacheHolder::Instance().setScale2x(config_scale2x);
// FIXME: basic gui setup; should not be here
GUI::Manager & gm = GUI::ManagerHolder::Instance();
SDL_Rect rect;
rect.x = 5;
rect.y = 50;
fps_label = new GUI::Label(rect, "", "F_MTEXT.FON", 1);
//fps_label->borderColor.r = fps_label->borderColor.unused = 200;
gm.add(fps_label, 5);
} }
@ -338,7 +498,7 @@ void print_position() {
Vector3D & e = OpenGL::CameraHolder::Instance().getEye(); Vector3D & e = OpenGL::CameraHolder::Instance().getEye();
Vector3D & u = OpenGL::CameraHolder::Instance().getUp(); Vector3D & u = OpenGL::CameraHolder::Instance().getUp();
if (!city->getViewMode()) { if (!city->getViewMode()) {
INFO << cities[city_num] << ": " << city->getCurrentSector()->getFullName() << std::endl << std::cout << cities[city_num] << ": " << city->getCurrentSector()->getFullName() << std::endl <<
"camera.setCenter(" << v.x << ", " << v.y << ", " << v.z << ")" << std::endl << "camera.setCenter(" << v.x << ", " << v.y << ", " << v.z << ")" << std::endl <<
"camera.setEye(" << e.x << ", " << e.y << ", " << e.z << ")" << std::endl << "camera.setEye(" << e.x << ", " << e.y << ", " << e.z << ")" << std::endl <<
"camera.setUp(" << u.x << ", " << u.y << ", " << u.z << ")" << std::endl << "camera.setUp(" << u.x << ", " << u.y << ", " << u.z << ")" << std::endl <<
@ -347,7 +507,7 @@ void print_position() {
} }
else { else {
GLfloat* cp = city->getCamPos(); GLfloat* cp = city->getCamPos();
INFO << cities[city_num] << ": " << city->getCurrentSector()->getFullName() << std::endl << std::cout << cities[city_num] << ": " << city->getCurrentSector()->getFullName() << std::endl <<
"city_view:setCamPosition(" << cp[0] << ", " << cp[1] << ", " << cp[2] << ")" << std::endl << "city_view:setCamPosition(" << cp[0] << ", " << cp[1] << ", " << cp[2] << ")" << std::endl <<
"city_view:setVisibleRange(" << city->getVisibleRange() << ")" << std::endl << "city_view:setVisibleRange(" << city->getVisibleRange() << ")" << std::endl <<
"city_view:setTopDownView( true )" << std::endl; "city_view:setTopDownView( true )" << std::endl;
@ -389,12 +549,13 @@ void handleKeyUp( SDL_keysym *keysym) {
void draw_mapmode(); void draw_mapmode();
void create_ped_at(const Vector3D v) { void create_ped_at(const Vector3D v) {
OpenGTA::Pedestrian p(Vector3D(0.3f, 0.5f, 0.3f), v, 0xffffffff); OpenGTA::Pedestrian p(Vector3D(0.2f, 0.5f, 0.2f), v, 0xffffffff);
p.remap = OpenGTA::StyleHolder::Instance().get().getRandomPedRemapNumber(); p.remap = OpenGTA::StyleHolder::Instance().get().getRandomPedRemapNumber();
INFO << "using remap: " << p.remap << std::endl; INFO << "using remap: " << p.remap << std::endl;
OpenGTA::Pedestrian & pr = OpenGTA::SpriteManagerHolder::Instance().addPed(p); OpenGTA::Pedestrian & pr = OpenGTA::SpriteManagerHolder::Instance().addPed(p);
pr.switchToAnim(1); pr.switchToAnim(1);
OpenGTA::LocalPlayer::Instance().setCtrl(pr.m_control); OpenGTA::LocalPlayer::Instance().setCtrl(pr.m_control);
GUI::create_ingame_gui(1);
//pr.m_control = &OpenGTA::LocalPlayer::Instance(); //pr.m_control = &OpenGTA::LocalPlayer::Instance();
//OpenGTA::SpriteManagerHolder::Instance().getPedById(0xffffffff).giveItem(1, 255); //OpenGTA::SpriteManagerHolder::Instance().getPedById(0xffffffff).giveItem(1, 255);
} }
@ -471,7 +632,7 @@ void add_auto_ped() {
v.y += 0.9f; v.y += 0.9f;
//INFO << v.x << " " << v.y << " " << v.z << std::endl; //INFO << v.x << " " << v.y << " " << v.z << std::endl;
Sint16 remap = OpenGTA::StyleHolder::Instance().get().getRandomPedRemapNumber(); Sint16 remap = OpenGTA::StyleHolder::Instance().get().getRandomPedRemapNumber();
OpenGTA::Pedestrian p(Vector3D(0.3f, 0.5f, 0.3f), v, id, remap); OpenGTA::Pedestrian p(Vector3D(0.2f, 0.5f, 0.2f), v, id, remap);
OpenGTA::SpriteManagerHolder::Instance().addPed(p); OpenGTA::SpriteManagerHolder::Instance().addPed(p);
OpenGTA::Pedestrian & pr2 = OpenGTA::SpriteManagerHolder::Instance().getPedById(id); OpenGTA::Pedestrian & pr2 = OpenGTA::SpriteManagerHolder::Instance().getPedById(id);
pr2.switchToAnim(1); pr2.switchToAnim(1);
@ -486,6 +647,7 @@ void add_auto_ped() {
void toggle_player_run() { void toggle_player_run() {
OpenGTA::PedController * pc = &OpenGTA::LocalPlayer::Instance().getCtrl(); OpenGTA::PedController * pc = &OpenGTA::LocalPlayer::Instance().getCtrl();
INFO << std::endl;
if (!pc) { if (!pc) {
WARN << "no player yet!" << std::endl; WARN << "no player yet!" << std::endl;
@ -497,6 +659,69 @@ void toggle_player_run() {
pc->setRunning(false); pc->setRunning(false);
} }
void show_gamma_config() {
OpenGL::Screen & screen = OpenGL::ScreenHolder::Instance();
GUI::Manager & gm = GUI::ManagerHolder::Instance();
if (gamma_slide) {
SDL_Rect r;
r.x = screen.getWidth() / 2;
r.y = screen.getHeight() / 2;
r.w = 200;
r.h = 30;
GUI::ScrollBar * sb = new GUI::ScrollBar(GUI::GAMMA_SCROLLBAR_ID, r);
sb->color.r = sb->color.g = sb->color.b = 180;
sb->color.unused = 255;
sb->innerColor.r = 250;
sb->value = screen_gamma/2;
sb->changeCB = GUI::ScrollBar::SC_Functor(GUI::screen_gamma_callback);
gm.add(sb, 90);
r.y += 40;
std::ostringstream os;
os << "Gamma: " << screen_gamma;
GUI::Label * l = new GUI::Label(GUI::GAMMA_LABEL_ID, r, os.str(), "F_MTEXT.FON", 1);
gm.add(l, 80);
screen.setSystemMouseCursor(true);
}
else {
gm.removeById(GUI::GAMMA_SCROLLBAR_ID);
gm.removeById(GUI::GAMMA_LABEL_ID);
screen.setSystemMouseCursor(false);
}
}
void car_toggle() {
OpenGTA::Pedestrian & pped = OpenGTA::LocalPlayer::Instance().getPed();
Vector3D pos = pped.pos;
std::list<OpenGTA::Car> & list = OpenGTA::SpriteManagerHolder::Instance().getList<OpenGTA::Car>();
float min_dist = 360;
float _d;
std::list<OpenGTA::Car>::iterator j = list.end();
for (std::list<OpenGTA::Car>::iterator i = list.begin(); i != list.end(); i++) {
if ((_d = Util::distance(pos, i->pos)) < min_dist) {
j = i;
min_dist = _d;
}
}
assert(j != list.end());
std::cout << j->id() << " " << j->pos.x << ", " << j->pos.y << ", " << j->pos.z << std::endl;
Vector3D p_door(j->carInfo.door[0].rpx / 64.0f, 0,
j->carInfo.door[0].rpy / 64.0f);
Vector3D p_door_global = Transform(p_door, j->m_M);
p_door_global.y += 0.2f;
std::cout << p_door_global.x << ", " << p_door_global.y << ", " << p_door_global.z << std::endl;
test_dot = p_door_global;
//pped.aiMode = 1;
//pped.aiData.pos1 = p_door_global;
OpenGTA::AI::Pedestrian::walk_pavement(&pped);
}
void handleKeyPress( SDL_keysym *keysym ) { void handleKeyPress( SDL_keysym *keysym ) {
GLfloat* cp = city->getCamPos(); GLfloat* cp = city->getCamPos();
mapPos[0] = cp[0]; mapPos[1] = cp[1]; mapPos[2] = cp[2]; mapPos[0] = cp[0]; mapPos[1] = cp[1]; mapPos[2] = cp[2];
@ -530,6 +755,13 @@ void handleKeyPress( SDL_keysym *keysym ) {
//zoomToTrain(next_station_zoom++); //zoomToTrain(next_station_zoom++);
//if (next_station_zoom >= OpenGTA::SpriteManagerHolder::Instance().trainSystem.getNumTrains()) //if (next_station_zoom >= OpenGTA::SpriteManagerHolder::Instance().trainSystem.getNumTrains())
// next_station_zoom = 0; // next_station_zoom = 0;
global_Restart = 1;
global_Done = 1;
return;
{
Vector3D p(cam.getEye());
OpenGTA::MapHolder::Instance().get().getNearestLocationByType(0, p.x, p.z);
}
break; break;
case SDLK_F2: case SDLK_F2:
bbox_toggle = (bbox_toggle ? 0 : 1); bbox_toggle = (bbox_toggle ? 0 : 1);
@ -558,8 +790,12 @@ void handleKeyPress( SDL_keysym *keysym ) {
cam.releaseFollowMode(); cam.releaseFollowMode();
OpenGTA::SpriteManagerHolder::Instance().removePedById(0xffffffff); OpenGTA::SpriteManagerHolder::Instance().removePedById(0xffffffff);
OpenGTA::SpriteManagerHolder::Instance().removeDeadStuff(); OpenGTA::SpriteManagerHolder::Instance().removeDeadStuff();
GUI::remove_ingame_gui();
} }
break; break;
case SDLK_RETURN:
car_toggle();
break;
case SDLK_F5: case SDLK_F5:
draw_arrows = (draw_arrows ? 0 : 1); draw_arrows = (draw_arrows ? 0 : 1);
city->setDrawHeadingArrows(draw_arrows); city->setDrawHeadingArrows(draw_arrows);
@ -579,6 +815,10 @@ void handleKeyPress( SDL_keysym *keysym ) {
case SDLK_F10: case SDLK_F10:
city->setDrawLines(city->getDrawLines() ? 0 : 1); city->setDrawLines(city->getDrawLines() ? 0 : 1);
break; break;
case SDLK_F12:
gamma_slide = (gamma_slide ? 0 : 1);
show_gamma_config();
break;
case SDLK_LSHIFT: case SDLK_LSHIFT:
toggle_player_run(); toggle_player_run();
break; break;
@ -658,11 +898,16 @@ void handleKeyPress( SDL_keysym *keysym ) {
OpenGTA::LocalPlayer::Instance().getCtrl().setMoveBack(); OpenGTA::LocalPlayer::Instance().getCtrl().setMoveBack();
break; break;
case 'f': case 'f':
//FIXME: simply ignored on windows for now
#ifndef WIN32
OpenGL::ScreenHolder::Instance().toggleFullscreen(); OpenGL::ScreenHolder::Instance().toggleFullscreen();
#endif
#if 0
#ifdef WIN32 #ifdef WIN32
city->resetTextures(); city->resetTextures();
m_font->resetTextures(); //m_font->resetTextures();
OpenGL::SpriteCacheHolder::Instance().clearAll(); OpenGL::SpriteCacheHolder::Instance().clearAll();
#endif
#endif #endif
break; break;
case 'r': case 'r':
@ -723,20 +968,35 @@ void drawScene(Uint32 ticks) {
OpenGL::ScreenHolder::Instance().set3DProjection(); OpenGL::ScreenHolder::Instance().set3DProjection();
city->draw(ticks); city->draw(ticks);
glColor3f(1, 0, 0);
glDisable(GL_TEXTURE_2D);
glBegin(GL_POINTS);
glVertex3f(test_dot.x, test_dot.y, test_dot.z);
glEnd();
glEnable(GL_TEXTURE_2D);
glColor3f(1, 1, 1);
OpenGL::ScreenHolder::Instance().setFlatProjection(); OpenGL::ScreenHolder::Instance().setFlatProjection();
glDisable(GL_DEPTH_TEST);
glPushMatrix(); glPushMatrix();
glTranslatef(10, 10, 0); glTranslatef(10, 10, 0);
m_font->drawString(city->getCurrentSector()->getFullName()); OpenGL::DrawableFont & m_font = OpenGTA::FontCacheHolder::Instance().getFont("F_MTEXT.FON", 1);
m_font.drawString(city->getCurrentSector()->getFullName());
glPopMatrix(); glPopMatrix();
glPushMatrix();
/*glPushMatrix();
glTranslatef(5, 50, 0); glTranslatef(5, 50, 0);
std::ostringstream strstr; std::ostringstream strstr;
strstr << fps << " fps"; strstr << fps << " fps";
m_font->drawString(strstr.str()); m_font->drawString(strstr.str());
glPopMatrix(); glPopMatrix();*/
GUI::ManagerHolder::Instance().draw();
num_frames_drawn += 1; num_frames_drawn += 1;
glEnable(GL_DEPTH_TEST);
SDL_GL_SwapBuffers(); SDL_GL_SwapBuffers();
} }
@ -747,9 +1007,9 @@ void draw_mapmode() {
bool done_map = false; bool done_map = false;
OpenGL::Screen & screen = OpenGL::ScreenHolder::Instance(); OpenGL::Screen & screen = OpenGL::ScreenHolder::Instance();
screen.setSystemMouseCursor(true); screen.setSystemMouseCursor(true);
GLfloat _scale = 1; glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat dx = 0; glDisable(GL_DEPTH_TEST);
GLfloat dy = 0; INFO << map_tex.coords[1].u << std::endl;
while(!done_map) { while(!done_map) {
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
switch(event.type) { switch(event.type) {
@ -761,31 +1021,20 @@ void draw_mapmode() {
case SDLK_ESCAPE: case SDLK_ESCAPE:
done_map = true; done_map = true;
break; break;
case '-':
_scale += 0.1f;
break;
case '+':
_scale -= 0.1f;
break;
case SDLK_LEFT:
dx -= 0.1f;
break;
case SDLK_RIGHT:
dx += 0.1f;
break;
case SDLK_UP:
dy += 0.1f;
break;
case SDLK_DOWN:
dy -= 0.1f;
break;
default: default:
break; break;
} }
break; break;
case SDL_MOUSEBUTTONDOWN:
INFO << event.button.x / 600.0f * 255<< " " << event.button.y / 600.0f * 255 << std::endl;
mapPos[0] = event.button.x / 600.0f * 255;
mapPos[2] = event.button.y / 600.0f * 255;
//mapPos[1] = 10;
done_map = true;
break;
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
// std::cout << "Mouse move: x " << event.motion.x << " y " << std::cout << "Mouse move: x " << event.motion.x << " y " <<
// event.motion.y << std::endl; event.motion.y << std::endl;
break; break;
default: default:
break; break;
@ -796,119 +1045,71 @@ void draw_mapmode() {
screen.setFlatProjection(); screen.setFlatProjection();
glBindTexture(GL_TEXTURE_2D, map_tex.inPage); glBindTexture(GL_TEXTURE_2D, map_tex.inPage);
glMatrixMode(GL_TEXTURE); //glMatrixMode(GL_TEXTURE);
glLoadIdentity(); //if (_scale < 1)
glScalef(_scale, _scale, 1); // glScalef(_scale, _scale, 1);
glTranslatef(dx, dy, 0);
uint32_t h = screen.getHeight();
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f(map_tex.coords[0].u, map_tex.coords[0].v); glTexCoord2f(0, 0);
glVertex2i(0, 0); glVertex2i(0, 0);
glTexCoord2f(map_tex.coords[1].u, map_tex.coords[0].v); glTexCoord2f(map_tex.coords[1].u, 0);
glVertex2i(screen.getWidth(), 0); glVertex2i(h, 0);
glTexCoord2f(map_tex.coords[1].u, map_tex.coords[1].v); glTexCoord2f(map_tex.coords[1].u, map_tex.coords[1].v);
glVertex2i(screen.getWidth(), screen.getHeight()); glVertex2i(h, h);
glTexCoord2f(map_tex.coords[0].u, map_tex.coords[1].v); glTexCoord2f(0, map_tex.coords[1].v);
glVertex2i(0, screen.getHeight()); glVertex2i(0, h);
glEnd(); glEnd();
const OpenGTA::Map::LocationMap & lmap = OpenGTA::MapHolder::Instance().get().getLocationMap();
OpenGTA::Map::LocationMap::const_iterator i = lmap.begin();
glDisable(GL_TEXTURE_2D);
while (i != lmap.end()) {
if (i->first == 2) {
i++;
continue;
}
uint8_t l_type = i->first;
float l_x, l_y;
l_x = i->second->x / 255.0f * h;// * map_tex.coords[1].u;
l_y = i->second->y / 255.0f * h;// * map_tex.coords[1].u;
//INFO << int(l_type) << ": " << l_x << " " << l_y << std::endl;
glBegin(GL_LINE_STRIP);
glVertex2f(l_x - 5, l_y - 5);
glVertex2f(l_x + 5, l_y - 5);
glVertex2f(l_x + 5, l_y + 5);
glVertex2f(l_x - 5, l_y + 5);
glEnd();
++i;
}
glEnable(GL_TEXTURE_2D);
SDL_GL_SwapBuffers(); SDL_GL_SwapBuffers();
SDL_Delay(20); SDL_Delay(20);
} }
screen.setSystemMouseCursor(false); screen.setSystemMouseCursor(false);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_TEXTURE); glMatrixMode(GL_TEXTURE);
glLoadIdentity(); glLoadIdentity();
// the texture class doesn't cleanup! // the texture class doesn't cleanup!
glDeleteTextures(1, &map_tex.inPage); glDeleteTextures(1, &map_tex.inPage);
} }
#if 0
void parse_args(int argc, char* argv[]) {
int index;
int c;
opterr = 0;
#ifdef WITH_LUA
#define VIEWER_FLAGS "s:w:h:c:m:g:l:f"
#else
#define VIEWER_FLAGS "w:h:c:m:g:l:f"
#endif
while ((c = getopt (argc, argv, VIEWER_FLAGS)) != -1)
switch (c)
{
#ifdef WITH_LUA
case 's':
script_file = optarg;
break;
#endif
case 'c':
highcolor_data = atoi(optarg);
break;
case 'm':
specific_map = std::string(optarg);
break;
case 'g':
specific_style = std::string(optarg);
break;
case 'w':
arg_screen_w = atoi(optarg);
break;
case 'h':
arg_screen_h = atoi(optarg);
break;
case 'l':
Util::Log::setOutputLevel(atoi(optarg));
break;
case 'f':
full_screen = true;
break;
case '?':
if (isprint (optopt))
ERROR << "Unknown option `-" << char(optopt) << "'" << std::endl;
else
ERROR << "Unknown option character `" << optopt << "'" << std::endl;
default:
abort ();
}
for (index = optind; index < argc; index++)
city_num = atoi(argv[index]);
if (city_num > 2) {
ERROR << "Invalid city number: " << city_num << std::endl;
exit(1);
}
}
void run_init(const char* prgname) {
PHYSFS_init("mapview");
//PHYSFS_addToSearchPath("gtadata.zip", 1);
Util::FileHelper & fh = GET_FILE_HELPER;
if (fh.existsInSystemFS(fh.getBaseDataPath()))
PHYSFS_addToSearchPath(GET_FILE_HELPER.getBaseDataPath().c_str(), 1);
else {
WARN << "Could not load data-source: " << fh.getBaseDataPath() <<" -- fallback to current directory"<< std::endl;
PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1);
}
if (fh.existsInSystemFS(fh.getModDataPath()))
PHYSFS_addToSearchPath(GET_FILE_HELPER.getModDataPath().c_str(), 0);
OpenGL::Screen & screen = OpenGL::ScreenHolder::Instance();
screen.setFullScreenFlag(full_screen);
screen.activate(arg_screen_w, arg_screen_h);
//SDL_EnableKeyRepeat( 100, SDL_DEFAULT_REPEAT_INTERVAL );
}
#endif
void run_main() { void run_main() {
SDL_Event event; SDL_Event event;
OpenGTA::MainMsgHolder::Instance().load("ENGLISH.FXT"); const char * lang = getenv("OGTA_LANG");
if (!lang)
lang = getenv("LANG");
if (!lang)
lang = "en";
OpenGTA::MainMsgHolder::Instance().load(Util::FileHelper::lang2MsgFilename(lang));
m_font = new OpenGL::DrawableFont(); //m_font = new OpenGL::DrawableFont();
m_font->loadFont("F_MTEXT.FON"); //m_font->loadFont("F_MTEXT.FON");
m_font->setScale(1); //m_font->setScale(1);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT, GL_FILL); glPolygonMode(GL_FRONT, GL_FILL);
@ -917,7 +1118,7 @@ void run_main() {
//glEnable(GL_BLEND); //glEnable(GL_BLEND);
//glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); //glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable(GL_ALPHA_TEST); glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0); glAlphaFunc(GL_GREATER, 2/255.0f);//0);
city = new OpenGTA::CityView(); city = new OpenGTA::CityView();
if (specific_map.size() > 0 && specific_style.size() > 0) { if (specific_map.size() > 0 && specific_style.size() > 0) {
@ -929,13 +1130,14 @@ void run_main() {
else else
city->loadMap(cities[city_num], styles_8[city_num]); city->loadMap(cities[city_num], styles_8[city_num]);
} }
if (city_blocks_area > -1)
city->setVisibleRange(city_blocks_area);
city->setPosition(mapPos[0], mapPos[1], mapPos[2]); city->setPosition(mapPos[0], mapPos[1], mapPos[2]);
OpenGL::Camera & cam = OpenGL::CameraHolder::Instance(); OpenGL::Camera & cam = OpenGL::CameraHolder::Instance();
//cam.setVectors( Vector3D(4, 10, 4), Vector3D(4, 0.0f, 4.0f), Vector3D(0, 0, -1) ); //cam.setVectors( Vector3D(4, 10, 4), Vector3D(4, 0.0f, 4.0f), Vector3D(0, 0, -1) );
cam.setVectors( Vector3D(12, 20, 12), Vector3D(13.0f, 19.0f, 13.0f), Vector3D(0, 1, 0) ); cam.setVectors( Vector3D(12, 20, 12), Vector3D(13.0f, 19.0f, 13.0f), Vector3D(0, 1, 0) );
#ifdef TIMER_OPENSTEER_CLOCK #ifdef TIMER_OPENSTEER_CLOCK
Timer & timer = TimerHolder::Instance(); Timer & timer = TimerHolder::Instance();
timer.update(); timer.update();
@ -948,13 +1150,14 @@ void run_main() {
#ifdef WITH_LUA #ifdef WITH_LUA
OpenGTA::Script::LuaVM & vm = OpenGTA::Script::LuaVMHolder::Instance(); OpenGTA::Script::LuaVM & vm = OpenGTA::Script::LuaVMHolder::Instance();
vm.setCityView(*city); vm.setCityView(*city);
vm.setMap(OpenGTA::MapHolder::Instance().get());
if (script_file) if (script_file)
vm.runFile(script_file); vm.runFile(script_file);
//vm.runString("function game_tick() print('tick...') end");
bool vm_tick_ok = true; bool vm_tick_ok = true;
script_last_tick = last_tick; script_last_tick = last_tick;
#endif #endif
GUI::Manager & guiManager = GUI::ManagerHolder::Instance();
while(!global_Done && !global_EC) { while(!global_Done && !global_EC) {
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
@ -980,6 +1183,9 @@ void run_main() {
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
//std::cout << "Mouse move: x " << float(event.motion.x)/screen->w << " y " << float(event.motion.y)/screen->h << std::endl; //std::cout << "Mouse move: x " << float(event.motion.x)/screen->w << " y " << float(event.motion.y)/screen->h << std::endl;
break; break;
case SDL_MOUSEBUTTONDOWN:
guiManager.receive(event.button);
break;
default: default:
break; break;
} }
@ -992,6 +1198,8 @@ void run_main() {
#endif #endif
OpenGTA::SpriteManagerHolder::Instance().update(now_ticks); OpenGTA::SpriteManagerHolder::Instance().update(now_ticks);
city->blockAnims->update(now_ticks); city->blockAnims->update(now_ticks);
GUI::ManagerHolder::Instance().update(now_ticks);
GUI::update_ingame_gui_values();
if (!paused) { if (!paused) {
drawScene(now_ticks - last_tick); drawScene(now_ticks - last_tick);
last_tick = now_ticks; last_tick = now_ticks;
@ -1018,9 +1226,19 @@ void run_main() {
fps = num_frames_drawn / 2; fps = num_frames_drawn / 2;
num_frames_drawn = 0; num_frames_drawn = 0;
fps_last_tick = now_ticks; fps_last_tick = now_ticks;
std::ostringstream os;
os << fps << " fps";
fps_label->text = os.str();
#ifdef WITH_LUA
vm.setGlobalInt("current_fps", fps);
#endif
} }
//#endif //#endif
// SDL_Delay(10); // SDL_Delay(10);
} }
#ifdef WITH_LUA
vm.runFile("scripts/dump_config.lua");
#endif
} }