1 /*
2  * Copyright 2011-2012 Arx Libertatis Team (see the AUTHORS file)
3  *
4  * This file is part of Arx Libertatis.
5  *
6  * Arx Libertatis is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Arx Libertatis is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Arx Libertatis.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 /* Based on:
20 ===========================================================================
21 ARX FATALIS GPL Source Code
22 Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
23 
24 This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
25 
26 Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
27 License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
28 
29 Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
30 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31 
32 You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code.  If not, see
33 <http://www.gnu.org/licenses/>.
34 
35 In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
36 additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
37 Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
38 
39 If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
40 ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
41 ===========================================================================
42 */
43 // Code: Cyril Meynier
44 //
45 // Copyright (c) 1999-2000 ARKANE Studios SA. All rights reserved
46 
47 #include "physics/Attractors.h"
48 
49 #include "game/Entity.h"
50 #include "game/EntityManager.h"
51 #include "graphics/Math.h"
52 #include "scene/Interactive.h"
53 
54 struct ARX_SPECIAL_ATTRACTOR {
55 	long	ionum;  // -1 == not defined
56 	float	power;
57 	float	radius;
58 };
59 
60 static const size_t MAX_ATTRACTORS = 16;
61 static ARX_SPECIAL_ATTRACTOR attractors[MAX_ATTRACTORS];
62 
ARX_SPECIAL_ATTRACTORS_Reset()63 void ARX_SPECIAL_ATTRACTORS_Reset() {
64 	for(size_t i = 0; i < MAX_ATTRACTORS; i++) {
65 		attractors[i].ionum = -1;
66 	}
67 }
68 
ARX_SPECIAL_ATTRACTORS_Remove(long ionum)69 static void ARX_SPECIAL_ATTRACTORS_Remove(long ionum) {
70 	for(size_t i = 0; i < MAX_ATTRACTORS; i++) {
71 		if(attractors[i].ionum == ionum) {
72 			attractors[i].ionum = -1;
73 		}
74 	}
75 }
76 
ARX_SPECIAL_ATTRACTORS_Exist(long ionum)77 static long ARX_SPECIAL_ATTRACTORS_Exist(long ionum) {
78 	for(size_t i = 0; i < MAX_ATTRACTORS; i++) {
79 		if(attractors[i].ionum == ionum) {
80 			return i;
81 		}
82 	}
83 	return -1;
84 }
85 
ARX_SPECIAL_ATTRACTORS_Add(long ionum,float power,float radius)86 bool ARX_SPECIAL_ATTRACTORS_Add(long ionum, float power, float radius) {
87 
88 	if(power == 0.f) {
89 		ARX_SPECIAL_ATTRACTORS_Remove(ionum);
90 	}
91 
92 	long tst;
93 	if((tst = ARX_SPECIAL_ATTRACTORS_Exist(ionum)) != -1) {
94 		attractors[tst].power = power;
95 		attractors[tst].radius = radius;
96 		return false;
97 	}
98 
99 	for(size_t i = 0; i < MAX_ATTRACTORS; i++) {
100 		if(attractors[i].ionum == -1) {
101 			attractors[i].ionum = ionum;
102 			attractors[i].power = power;
103 			attractors[i].radius = radius;
104 			return true;
105 		}
106 	}
107 
108 	return false;
109 }
110 
ARX_SPECIAL_ATTRACTORS_ComputeForIO(const Entity & ioo,Vec3f & force)111 void ARX_SPECIAL_ATTRACTORS_ComputeForIO(const Entity & ioo, Vec3f & force) {
112 
113 	force = Vec3f::ZERO;
114 
115 	for(size_t i = 0; i < MAX_ATTRACTORS; i++) {
116 
117 		if(attractors[i].ionum == -1 || !ValidIONum(attractors[i].ionum)) {
118 			continue;
119 		}
120 
121 		const Entity & io = *entities[attractors[i].ionum];
122 
123 		if(io.show != SHOW_FLAG_IN_SCENE || (io.ioflags & IO_NO_COLLISIONS)
124 			 || !(io.gameFlags & GFLAG_ISINTREATZONE)) {
125 			continue;
126 		}
127 
128 		float power = attractors[i].power;
129 		float dist = fdist(ioo.pos, io.pos);
130 
131 		if(dist > (ioo.physics.cyl.radius + io.physics.cyl.radius + 10.f) || power < 0.f) {
132 
133 			float max_radius = attractors[i].radius;
134 
135 			if(dist < max_radius) {
136 				float ratio_dist = 1.f - (dist / max_radius);
137 				Vec3f vect = io.pos - ioo.pos;
138 				fnormalize(vect);
139 				power *= ratio_dist * 0.01f;
140 				force = vect * power;
141 			}
142 		}
143 
144 	}
145 }
146