• R/O
  • SSH
  • HTTPS

marathon: コミット


コミットメタ情報

リビジョン508 (tree)
日時2011-12-15 19:56:38
作者logue

ログメッセージ

・チェックボックスの描画が大きくなってしまう問題を解消。(sdl_dialogs.cpp、sdl_widgets.cpp)
・日本語を読み込むとき不要なので、Font.fntAを読み込みに行かないようにした。(sdl_fonts.cpp)
・公式版r4658とマージ。(OpenGL使用時のアスペクト比の問題など)
◆5gHss7FzOA氏のコードをコミット。
・インターフェースの文字化けが治った。(FontHandler.cpp)
・設定画面で落ちるバグを修正。
・一部イベント割り当てが間違っていた。(preferences.cpp)

変更サマリ

差分

--- marathon/trunk/Source_Files/Lua/lua_monsters.cpp (revision 507)
+++ marathon/trunk/Source_Files/Lua/lua_monsters.cpp (revision 508)
@@ -1,1059 +1,1059 @@
1-/*
2-LUA_MONSTERS.CPP
3-
4- Copyright (C) 2008 by Gregory Smith
5-
6- This program 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- This program 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- This license is contained in the file "COPYING",
17- which is included with this source code; it is available online at
18- http://www.gnu.org/licenses/gpl.html
19-
20- Implements the Lua monster classes
21-*/
22-
23-#include "lua_monsters.h"
24-#include "lua_map.h"
25-#include "lua_objects.h"
26-#include "lua_player.h"
27-#include "lua_templates.h"
28-
29-#include "flood_map.h"
30-#include "monsters.h"
31-#include "player.h"
32-
33-#include <boost/bind.hpp>
34-
35-#define DONT_REPEAT_DEFINITIONS
36-#include "monster_definitions.h"
37-
38-#ifdef HAVE_LUA
39-
40-const float AngleConvert = 360/float(FULL_CIRCLE);
41-
42-static inline bool powerOfTwo(int32 x)
43-{
44- return !((x-1) & x);
45-}
46-
47-char Lua_MonsterClass_Name[] = "monster_class";
48-typedef L_Enum<Lua_MonsterClass_Name, int32> Lua_MonsterClass;
49-
50-bool Lua_MonsterClass_Valid(int32 index)
51-{
52- return index >= 1 && index <= _class_yeti && powerOfTwo(index);
53-}
54-
55-char Lua_MonsterClasses_Name[] = "MonsterClasses";
56-typedef L_EnumContainer<Lua_MonsterClasses_Name, Lua_MonsterClass> Lua_MonsterClasses;
57-
58-template<>
59-int L_Container<Lua_MonsterClasses_Name, Lua_MonsterClass>::_iterator(lua_State *L)
60-{
61- int32 index = static_cast<int32>(lua_tonumber(L, lua_upvalueindex(1)));
62- while (index < Length())
63- {
64- if (Lua_MonsterClass::Valid(1 << index))
65- {
66- Lua_MonsterClass::Push(L, 1 << index);
67- lua_pushnumber(L, ++index);
68- lua_replace(L, lua_upvalueindex(1));
69- return 1;
70- }
71- else
72- {
73- ++index;
74- }
75- }
76-
77- lua_pushnil(L);
78- return 1;
79-}
80-
81-extern object_frequency_definition* monster_placement_info;
82-
83-char Lua_MonsterType_Enemies_Name[] = "monster_type_enemies";
84-typedef L_Class<Lua_MonsterType_Enemies_Name> Lua_MonsterType_Enemies;
85-
86-static int Lua_MonsterType_Enemies_Get(lua_State *L)
87-{
88- int monster_type = Lua_MonsterType_Enemies::Index(L, 1);
89- int enemy_class = Lua_MonsterClass::ToIndex(L, 2);
90-
91- monster_definition *definition = get_monster_definition_external(monster_type);
92- lua_pushboolean(L, definition->enemies & enemy_class);
93- return 1;
94-}
95-
96-static int Lua_MonsterType_Enemies_Set(lua_State *L)
97-{
98- if (!lua_isboolean(L, 3))
99- return luaL_error(L, "enemies: incorrect argument type");
100-
101- int monster_type = Lua_MonsterType_Enemies::Index(L, 1);
102- int enemy_class = Lua_MonsterClass::ToIndex(L, 2);
103- bool enemy = lua_toboolean(L, 3);
104- monster_definition *definition = get_monster_definition_external(monster_type);
105- if (enemy)
106- {
107- definition->enemies = definition->enemies | enemy_class;
108- }
109- else
110- {
111- definition->enemies = definition->enemies & ~(enemy_class);
112- }
113-
114- return 0;
115-}
116-
117-const luaL_reg Lua_MonsterType_Enemies_Metatable[] = {
118- {"__index", Lua_MonsterType_Enemies_Get},
119- {"__newindex", Lua_MonsterType_Enemies_Set},
120- {0, 0}
121-};
122-
123-char Lua_MonsterType_Friends_Name[] = "monster_type_friends";
124-typedef L_Class<Lua_MonsterType_Friends_Name> Lua_MonsterType_Friends;
125-
126-static int Lua_MonsterType_Friends_Get(lua_State *L)
127-{
128- int monster_type = Lua_MonsterType_Friends::Index(L, 1);
129- int friend_class = Lua_MonsterClass::ToIndex(L, 2);
130-
131- monster_definition *definition = get_monster_definition_external(monster_type);
132- lua_pushboolean(L, definition->friends & friend_class);
133- return 1;
134-}
135-
136-static int Lua_MonsterType_Friends_Set(lua_State *L)
137-{
138- if (!lua_isboolean(L, 3))
139- return luaL_error(L, "enemies: incorrect argument type");
140-
141- int monster_type = Lua_MonsterType_Friends::Index(L, 1);
142- int friend_class = Lua_MonsterClass::ToIndex(L, 2);
143- bool friendly = lua_toboolean(L, 3);
144- monster_definition *definition = get_monster_definition_external(monster_type);
145- if (friendly)
146- {
147- definition->friends = definition->friends | friend_class;
148- }
149- else
150- {
151- definition->friends = definition->friends & ~(friend_class);
152- }
153-
154- return 0;
155-}
156-
157-const luaL_reg Lua_MonsterType_Friends_Metatable[] = {
158- {"__index", Lua_MonsterType_Friends_Get},
159- {"__newindex", Lua_MonsterType_Friends_Set},
160- {0, 0}
161-};
162-
163-char Lua_MonsterType_Immunities_Name[] = "monster_type_immunities";
164-typedef L_Class<Lua_MonsterType_Immunities_Name> Lua_MonsterType_Immunities;
165-
166-static int Lua_MonsterType_Immunities_Get(lua_State *L)
167-{
168- int monster_type = Lua_MonsterType_Immunities::Index(L, 1);
169- int damage_type = Lua_DamageType::ToIndex(L, 2);
170-
171- monster_definition *definition = get_monster_definition_external(monster_type);
172- lua_pushboolean(L, definition->immunities & (1 << damage_type));
173- return 1;
174-}
175-
176-static int Lua_MonsterType_Immunities_Set(lua_State *L)
177-{
178- if (!lua_isboolean(L, 3))
179- luaL_error(L, "immunities: incorrect argument type");
180-
181- int monster_type = Lua_MonsterType_Immunities::Index(L, 1);
182- int damage_type = Lua_DamageType::ToIndex(L, 2);
183- bool immune = lua_toboolean(L, 3);
184-
185- monster_definition *definition = get_monster_definition_external(monster_type);
186- if (immune)
187- {
188- definition->immunities |= (1 << damage_type);
189- }
190- else
191- {
192- definition->immunities &= ~(1 << damage_type);
193- }
194-
195- return 0;
196-}
197-
198-const luaL_reg Lua_MonsterType_Immunities_Metatable[] = {
199- {"__index", Lua_MonsterType_Immunities_Get},
200- {"__newindex", Lua_MonsterType_Immunities_Set},
201- {0, 0}
202-};
203-
204-char Lua_MonsterType_Weaknesses_Name[] = "monster_type_weaknesses";
205-typedef L_Class<Lua_MonsterType_Weaknesses_Name> Lua_MonsterType_Weaknesses;
206-
207-int Lua_MonsterType_Weaknesses_Get(lua_State *L)
208-{
209- int monster_type = Lua_MonsterType_Weaknesses::Index(L, 1);
210- int damage_type = Lua_DamageType::ToIndex(L, 2);
211-
212- monster_definition *definition = get_monster_definition_external(monster_type);
213- lua_pushboolean(L, definition->weaknesses & (1 << damage_type));
214- return 1;
215-}
216-
217-int Lua_MonsterType_Weaknesses_Set(lua_State *L)
218-{
219- if (!lua_isboolean(L, 3))
220- luaL_error(L, "immunities: incorrect argument type");
221-
222- int monster_type = Lua_MonsterType_Weaknesses::Index(L, 1);
223- int damage_type = Lua_DamageType::ToIndex(L, 2);
224- bool weakness = lua_toboolean(L, 3);
225-
226- monster_definition *definition = get_monster_definition_external(monster_type);
227- if (weakness)
228- {
229- definition->weaknesses |= (1 << damage_type);
230- }
231- else
232- {
233- definition->weaknesses &= ~(1 << damage_type);
234- }
235-
236- return 0;
237-}
238-
239-const luaL_reg Lua_MonsterType_Weaknesses_Metatable[] = {
240- {"__index", Lua_MonsterType_Weaknesses_Get},
241- {"__newindex", Lua_MonsterType_Weaknesses_Set},
242- {0, 0}
243-};
244-
245-char Lua_MonsterType_Name[] = "monster_type";
246-
247-static bool Lua_MonsterType_Valid(int16 index)
248-{
249- return index >= 0 && index < NUMBER_OF_MONSTER_TYPES;
250-}
251-
252-static int Lua_MonsterType_Get_Class(lua_State *L) {
253- monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
254- Lua_MonsterClass::Push(L, definition->_class);
255- return 1;
256-}
257-
258-static int Lua_MonsterType_Get_Enemies(lua_State *L) {
259- Lua_MonsterType_Enemies::Push(L, Lua_MonsterType::Index(L, 1));
260- return 1;
261-}
262-
263-static int Lua_MonsterType_Get_Height(lua_State *L) {
264- monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
265- lua_pushnumber(L, (double) definition->height / WORLD_ONE);
266- return 1;
267-}
268-
269-static int Lua_MonsterType_Get_Friends(lua_State *L) {
270- Lua_MonsterType_Friends::Push(L, Lua_MonsterType::Index(L, 1));
271- return 1;
272-}
273-
274-static int Lua_MonsterType_Get_Immunities(lua_State *L) {
275- Lua_MonsterType_Immunities::Push(L, Lua_MonsterType::Index(L, 1));
276- return 1;
277-}
278-
279-static int Lua_MonsterType_Get_Impact_Effect(lua_State *L) {
280- monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
281- Lua_EffectType::Push(L, definition->impact_effect);
282- return 1;
283-}
284-
285-static int Lua_MonsterType_Get_Initial_Count(lua_State* L)
286-{
287- lua_pushnumber(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].initial_count);
288- return 1;
289-}
290-
291-static int Lua_MonsterType_Get_Maximum_Count(lua_State* L)
292-{
293- lua_pushnumber(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].maximum_count);
294- return 1;
295-}
296-
297-
298-static int Lua_MonsterType_Get_Melee_Impact_Effect(lua_State *L) {
299- monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
300- Lua_EffectType::Push(L, definition->melee_impact_effect);
301- return 1;
302-}
303-
304-static int Lua_MonsterType_Get_Minimum_Count(lua_State* L)
305-{
306- lua_pushnumber(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].minimum_count);
307- return 1;
308-}
309-
310-static int Lua_MonsterType_Get_Radius(lua_State *L) {
311- monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
312- lua_pushnumber(L, (double) definition->radius / WORLD_ONE);
313- return 1;
314-}
315-
316-static int Lua_MonsterType_Get_Random_Chance(lua_State* L)
317-{
318- lua_pushnumber(L, (double) monster_placement_info[Lua_MonsterType::Index(L, 1)].random_chance / UINT16_MAX);
319- return 1;
320-}
321-
322-static int Lua_MonsterType_Get_Random_Count(lua_State* L)
323-{
324- lua_pushnumber(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].random_count);
325- return 1;
326-}
327-
328-static int Lua_MonsterType_Get_Random_Location(lua_State* L)
329-{
330- lua_pushboolean(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].flags & _reappears_in_random_location);
331- return 1;
332-}
333-
334-static int Lua_MonsterType_Get_Weaknesses(lua_State *L) {
335- Lua_MonsterType_Weaknesses::Push(L, Lua_MonsterType::Index(L, 1));
336- return 1;
337-}
338-
339-static int Lua_MonsterType_Get_Item(lua_State *L) {
340- monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
341- Lua_ItemType::Push(L, definition->carrying_item_type);
342- return 1;
343-}
344-
345-static int Lua_MonsterType_Set_Class(lua_State *L) {
346- monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
347- definition->_class = static_cast<int32>(Lua_MonsterClass::ToIndex(L, 2));
348- return 0;
349-}
350-
351-static int Lua_MonsterType_Set_Item(lua_State *L) {
352- int item_type = 0;
353- if (lua_isnumber(L, 2))
354- {
355- item_type = static_cast<int>(lua_tonumber(L, 2));
356- }
357- else if (lua_isnil(L, 2))
358- {
359- item_type = NONE;
360- }
361- else
362- return luaL_error(L, "item: incorrect argument type");
363-
364- monster_definition *definition = get_monster_definition_external(Lua_MonsterType::ToIndex(L, 1));
365-
366- definition->carrying_item_type = item_type;
367- return 0;
368-}
369-
370-static int Lua_MonsterType_Set_Initial_Count(lua_State* L)
371-{
372- if (lua_isnumber(L, 2))
373- {
374- monster_placement_info[Lua_MonsterType::Index(L, 1)].initial_count = lua_tonumber(L, 2);
375- }
376- else
377- {
378- return luaL_error(L, "initial_count: incorrect argument type");
379- }
380- return 0;
381-}
382-
383-static int Lua_MonsterType_Set_Maximum_Count(lua_State* L)
384-{
385- if (lua_isnumber(L, 2))
386- {
387- monster_placement_info[Lua_MonsterType::Index(L, 1)].maximum_count = lua_tonumber(L, 2);
388- }
389- else
390- {
391- return luaL_error(L, "maximum_count: incorrect argument type");
392- }
393- return 0;
394-}
395-
396-static int Lua_MonsterType_Set_Minimum_Count(lua_State* L)
397-{
398- if (lua_isnumber(L, 2))
399- {
400- monster_placement_info[Lua_MonsterType::Index(L, 1)].minimum_count = lua_tonumber(L, 2);
401- }
402- else
403- {
404- return luaL_error(L, "minimum_count: incorrect argument type");
405- }
406- return 0;
407-}
408-
409-static int Lua_MonsterType_Set_Random_Chance(lua_State* L)
410-{
411- if (lua_isnumber(L, 2))
412- {
413- monster_placement_info[Lua_MonsterType::Index(L, 1)].random_chance = static_cast<uint16>(lua_tonumber(L, 2) * UINT16_MAX + 0.5);
414- }
415- else
416- {
417- return luaL_error(L, "random_chance: incorrect argument type");
418- }
419- return 0;
420-}
421-
422-static int Lua_MonsterType_Set_Random_Count(lua_State* L)
423-{
424- if (lua_isnumber(L, 2))
425- {
426- monster_placement_info[Lua_MonsterType::Index(L, 1)].random_count = lua_tonumber(L, 2);
427- }
428- else
429- {
430- return luaL_error(L, "random_count: incorrect argument type");
431- }
432- return 0;
433-}
434-
435-static int Lua_MonsterType_Set_Random_Location(lua_State* L)
436-{
437- if (lua_isboolean(L, 2))
438- {
439- if (lua_toboolean(L, 2))
440- {
441- monster_placement_info[Lua_MonsterType::Index(L, 1)].flags |= _reappears_in_random_location;
442- }
443- else
444- {
445- monster_placement_info[Lua_MonsterType::Index(L, 1)].flags &= ~_reappears_in_random_location;
446- }
447- }
448- else
449- {
450- return luaL_error(L, "random_location: incorrect argument type");
451- }
452- return 0;
453-}
454-
455-const luaL_reg Lua_MonsterType_Get[] = {
456- {"class", Lua_MonsterType_Get_Class},
457- {"enemies", Lua_MonsterType_Get_Enemies},
458- {"friends", Lua_MonsterType_Get_Friends},
459- {"height", Lua_MonsterType_Get_Height},
460- {"immunities", Lua_MonsterType_Get_Immunities},
461- {"impact_effect", Lua_MonsterType_Get_Impact_Effect},
462- {"initial_count", Lua_MonsterType_Get_Initial_Count},
463- {"maximum_count", Lua_MonsterType_Get_Maximum_Count},
464- {"melee_impact_effect", Lua_MonsterType_Get_Melee_Impact_Effect},
465- {"minimum_count", Lua_MonsterType_Get_Minimum_Count},
466- {"item", Lua_MonsterType_Get_Item},
467- {"radius", Lua_MonsterType_Get_Radius},
468- {"random_count", Lua_MonsterType_Get_Random_Count},
469- {"random_location", Lua_MonsterType_Get_Random_Location},
470- {"total_available", Lua_MonsterType_Get_Random_Chance},
471- {"weaknesses", Lua_MonsterType_Get_Weaknesses},
472- {0, 0}
473-};
474-
475-const luaL_reg Lua_MonsterType_Set[] = {
476- {"class", Lua_MonsterType_Set_Class},
477- {"initial_count", Lua_MonsterType_Set_Initial_Count},
478- {"item", Lua_MonsterType_Set_Item},
479- {"maximum_count", Lua_MonsterType_Set_Maximum_Count},
480- {"minimum_count", Lua_MonsterType_Set_Minimum_Count},
481- {"random_chance", Lua_MonsterType_Set_Random_Chance},
482- {"random_location", Lua_MonsterType_Set_Random_Location},
483- {"total_available", Lua_MonsterType_Set_Random_Count},
484- {0, 0}
485-};
486-
487-char Lua_MonsterMode_Name[] = "monster_mode";
488-typedef L_Enum<Lua_MonsterMode_Name> Lua_MonsterMode;
489-
490-char Lua_MonsterModes_Name[] = "MonsterModes";
491-typedef L_EnumContainer<Lua_MonsterModes_Name, Lua_MonsterMode> Lua_MonsterModes;
492-
493-char Lua_MonsterAction_Name[] = "monster_action";
494-
495-char Lua_MonsterActions_Name[] = "MonsterActions";
496-typedef L_EnumContainer<Lua_MonsterActions_Name, Lua_MonsterAction> Lua_MonsterActions;
497-
498-char Lua_MonsterTypes_Name[] = "MonsterTypes";
499-typedef L_EnumContainer<Lua_MonsterTypes_Name, Lua_MonsterType> Lua_MonsterTypes;
500-
501-char Lua_Monster_Name[] = "monster";
502-
503-int Lua_Monster_Accelerate(lua_State *L)
504-{
505- if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4))
506- return luaL_error(L, "accelerate: incorrect argument type");
507-
508- short monster_index = Lua_Monster::Index(L, 1);
509- monster_data *monster = get_monster_data(monster_index);
510- double direction = static_cast<double>(lua_tonumber(L, 2));
511- double velocity = static_cast<double>(lua_tonumber(L, 3));
512- double vertical_velocity = static_cast<double>(lua_tonumber(L, 4));
513-
514- accelerate_monster(monster_index, static_cast<int>(vertical_velocity * WORLD_ONE), static_cast<int>(direction/AngleConvert), static_cast<int>(velocity * WORLD_ONE));
515- return 0;
516-}
517-
518-int Lua_Monster_Attack(lua_State *L)
519-{
520- short target = 0;
521- if (lua_isnumber(L, 2))
522- target = static_cast<short>(lua_tonumber(L, 2));
523- else if (Lua_Monster::Is(L, 2))
524- target = Lua_Monster::Index(L, 2);
525- else
526- return luaL_error(L, "attack: incorrect argument type");
527-
528- change_monster_target(Lua_Monster::Index(L, 1), target);
529- return 0;
530-}
531-
532-int Lua_Monster_Play_Sound(lua_State *L)
533-{
534- short sound_index = Lua_Sound::ToIndex(L, 2);
535- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
536- play_object_sound(monster->object_index, sound_index);
537- return 0;
538-}
539-
540-int Lua_Monster_Damage(lua_State *L)
541-{
542- if (!lua_isnumber(L, 2))
543- return luaL_error(L, "damage: incorrect argument type");
544-
545- int damage_amount = static_cast<int>(lua_tonumber(L, 2));
546- int damage_type = NONE;
547- if (lua_gettop(L) == 3)
548- {
549- damage_type = Lua_DamageType::ToIndex(L, 3);
550- }
551-
552- damage_definition damage;
553- if (damage_type != NONE)
554- damage.type = damage_type;
555- else
556- damage.type = _damage_fist;
557-
558- damage.base = damage_amount;
559- damage.random = 0;
560- damage.flags = 0;
561- damage.scale = FIXED_ONE;
562-
563- int monster_index = Lua_Monster::Index(L, 1);
564- monster_data *monster = get_monster_data(monster_index);
565- damage_monster(monster_index, NONE, NONE, &(monster->sound_location), &damage, NONE);
566- return 0;
567-}
568-
569-int Lua_Monster_Valid(int16 index)
570-{
571- if (index < 0 || index >= MAXIMUM_MONSTERS_PER_MAP)
572- return false;
573-
574- monster_data *monster = GetMemberWithBounds(monsters, index, MAXIMUM_MONSTERS_PER_MAP);
575- return (SLOT_IS_USED(monster));
576-}
577-
578-struct monster_pathfinding_data
579-{
580- struct monster_definition *definition;
581- struct monster_data *monster;
582-
583- bool cross_zone_boundaries;
584-};
585-
586-extern void advance_monster_path(short monster_index);
587-extern int32 monster_pathfinding_cost_function(short source_polygon_index, short line_index, short destination_polygon_index, void *data);
588-extern void set_monster_action(short monster_index, short action);
589-extern void set_monster_mode(short monster_index, short new_mode, short target_index);
590-
591-int Lua_Monster_Move_By_Path(lua_State *L)
592-{
593- int monster_index = Lua_Monster::Index(L, 1);
594- int polygon_index = 0;
595- if (lua_isnumber(L, 2))
596- {
597- polygon_index = static_cast<int>(lua_tonumber(L, 2));
598- if (!Lua_Polygon::Valid(polygon_index))
599- return luaL_error(L, "move_by_path: invalid polygon index");
600- }
601- else if (Lua_Polygon::Is(L, 2))
602- {
603- polygon_index = Lua_Polygon::Index(L, 2);
604- }
605- else
606- return luaL_error(L, "move_by_path: incorrect argument type");
607-
608- monster_data *monster = get_monster_data(monster_index);
609- if (MONSTER_IS_PLAYER(monster))
610- return luaL_error(L, "move_by_path: monster is player");
611-
612- monster_definition *definition = get_monster_definition_external(monster->type);
613- object_data *object = get_object_data(monster->object_index);
614- monster_pathfinding_data path;
615- world_point2d destination;
616-
617- if (!MONSTER_IS_ACTIVE(monster))
618- activate_monster(monster_index);
619-
620- if (monster->path != NONE)
621- {
622- delete_path(monster->path);
623- monster->path = NONE;
624- }
625-
626- SET_MONSTER_NEEDS_PATH_STATUS(monster, false);
627- path.definition = definition;
628- path.monster = monster;
629- path.cross_zone_boundaries = true;
630-
631- destination = get_polygon_data(polygon_index)->center;
632-
633- monster->path = new_path((world_point2d *) &object->location, object->polygon, &destination, polygon_index, 3 * definition->radius, monster_pathfinding_cost_function, &path);
634- if (monster->path == NONE)
635- {
636- if (monster->action != _monster_is_being_hit || MONSTER_IS_DYING(monster))
637- {
638- set_monster_action(monster_index, _monster_is_stationary);
639- }
640- set_monster_mode(monster_index, _monster_unlocked, NONE);
641- return 0;
642- }
643-
644- advance_monster_path(monster_index);
645- return 0;
646-}
647-
648-extern void add_object_to_polygon_object_list(short object_index, short polygon_index);
649-
650-int Lua_Monster_Position(lua_State *L)
651-{
652- if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4))
653- return luaL_error(L, "position: incorrect argument type");
654-
655- short polygon_index = 0;
656- if (lua_isnumber(L, 5))
657- {
658- polygon_index = static_cast<int>(lua_tonumber(L, 5));
659- if (!Lua_Polygon::Valid(polygon_index))
660- return luaL_error(L, "position: invalid polygon index");
661- }
662- else if (Lua_Polygon::Is(L, 5))
663- {
664- polygon_index = Lua_Polygon::Index(L, 5);
665- }
666- else
667- return luaL_error(L, "position: incorrect argument type");
668-
669- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
670- object_data *object = get_object_data(monster->object_index);
671- object->location.x = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
672- object->location.y = static_cast<int>(lua_tonumber(L, 3) * WORLD_ONE);
673- object->location.z = static_cast<int>(lua_tonumber(L, 4) * WORLD_ONE);
674-
675- if (polygon_index != object->polygon)
676- {
677- remove_object_from_polygon_object_list(monster->object_index);
678- add_object_to_polygon_object_list(monster->object_index, polygon_index);
679- }
680- return 0;
681-}
682-
683-
684-static int Lua_Monster_Get_Action(lua_State *L)
685-{
686- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
687- Lua_MonsterAction::Push(L, monster->action);
688- return 1;
689-}
690-
691-static int Lua_Monster_Get_Active(lua_State *L)
692-{
693- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
694- if (MONSTER_IS_PLAYER(monster))
695- return luaL_error(L, "active: monster is a player");
696-
697- lua_pushboolean(L, MONSTER_IS_ACTIVE(monster));
698- return 1;
699-}
700-
701-static int Lua_Monster_Get_External_Velocity(lua_State *L)
702-{
703- monster_data* monster = get_monster_data(Lua_Monster::Index(L, 1));
704- lua_pushnumber(L, (double) monster->external_velocity / WORLD_ONE);
705- return 1;
706-}
707-
708-static int Lua_Monster_Get_Facing(lua_State *L)
709-{
710- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
711- object_data *object = get_object_data(monster->object_index);
712- lua_pushnumber(L, (double) object->facing * AngleConvert);
713- return 1;
714-}
715-
716-static int Lua_Monster_Get_Mode(lua_State *L)
717-{
718- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
719- Lua_MonsterMode::Push(L, monster->mode);
720- return 1;
721-}
722-
723-static int Lua_Monster_Get_Player(lua_State *L)
724-{
725- int monster_index = Lua_Monster::Index(L, 1);
726- monster_data *monster = get_monster_data(monster_index);
727- if (MONSTER_IS_PLAYER(monster))
728- Lua_Player::Push(L, monster_index_to_player_index(monster_index));
729- else
730- lua_pushnil(L);
731-
732- return 1;
733-}
734-
735-static int Lua_Monster_Get_Polygon(lua_State *L)
736-{
737- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
738- object_data *object = get_object_data(monster->object_index);
739- Lua_Polygon::Push(L, object->polygon);
740- return 1;
741-}
742-
743-static int Lua_Monster_Get_Type(lua_State *L)
744-{
745- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
746- Lua_MonsterType::Push(L, monster->type);
747- return 1;
748-}
749-
750-static int Lua_Monster_Get_Valid(lua_State *L)
751-{
752- lua_pushboolean(L, Lua_Monster::Valid(Lua_Monster::Index(L, 1)));
753- return 1;
754-}
755-
756-static int Lua_Monster_Get_Vertical_Velocity(lua_State *L)
757-{
758- monster_data* monster = get_monster_data(Lua_Monster::Index(L, 1));
759- lua_pushnumber(L, (double) monster->vertical_velocity / WORLD_ONE);
760- return 1;
761-}
762-
763-static int Lua_Monster_Get_Visible(lua_State *L)
764-{
765- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
766- object_data *object = get_object_data(monster->object_index);
767- lua_pushboolean(L, OBJECT_IS_VISIBLE(object));
768- return 1;
769-}
770-
771-static int Lua_Monster_Get_Vitality(lua_State *L)
772-{
773- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
774- lua_pushnumber(L, monster->vitality);
775- return 1;
776-}
777-
778-static int Lua_Monster_Get_X(lua_State *L)
779-{
780- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
781- object_data *object = get_object_data(monster->object_index);
782- lua_pushnumber(L, (double) object->location.x / WORLD_ONE);
783- return 1;
784-}
785-
786-static int Lua_Monster_Get_Y(lua_State *L)
787-{
788- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
789- object_data *object = get_object_data(monster->object_index);
790- lua_pushnumber(L, (double) object->location.y / WORLD_ONE);
791- return 1;
792-}
793-
794-static int Lua_Monster_Get_Z(lua_State *L)
795-{
796- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
797- object_data *object = get_object_data(monster->object_index);
798- lua_pushnumber(L, (double) object->location.z / WORLD_ONE);
799- return 1;
800-}
801-
802-static int Lua_Monster_Set_Active(lua_State *L)
803-{
804- if (!lua_isboolean(L, 2))
805- return luaL_error(L, "active: incorrect argument type");
806-
807- bool activate = lua_toboolean(L, 2);
808- int monster_index = Lua_Monster::Index(L, 1);
809- monster_data *monster = get_monster_data(monster_index);
810- if (MONSTER_IS_PLAYER(monster))
811- return luaL_error(L, "active: monster is a player");
812- if (activate)
813- {
814- if (!MONSTER_IS_ACTIVE(monster))
815- activate_monster(monster_index);
816- }
817- else
818- {
819- if (MONSTER_IS_ACTIVE(monster))
820- deactivate_monster(monster_index);
821- }
822- return 0;
823-}
824-
825-static int Lua_Monster_Set_External_Velocity(lua_State *L)
826-{
827- if (!lua_isnumber(L, 2))
828- return luaL_error(L, "external_velocity: incorrect argument type");
829-
830- monster_data* monster = get_monster_data(Lua_Monster::Index(L, 1));
831- monster->external_velocity = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
832- return 0;
833-}
834-
835-static int Lua_Monster_Set_Facing(lua_State *L)
836-{
837- if (!lua_isnumber(L, 2))
838- return luaL_error(L, "facing: incorrect argument type");
839-
840- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
841- object_data *object = get_object_data(monster->object_index);
842- object->facing = static_cast<int>(lua_tonumber(L, 2) / AngleConvert);
843- return 0;
844-}
845-
846-static int Lua_Monster_Set_Vertical_Velocity(lua_State *L)
847-{
848- if (!lua_isnumber(L, 2))
849- return luaL_error(L, "vertical_velocity: incorrect argument type");
850-
851- monster_data* monster = get_monster_data(Lua_Monster::Index(L, 1));
852- monster->vertical_velocity = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
853- return 0;
854-}
855-
856-static int Lua_Monster_Set_Visible(lua_State *L) {
857- int monster_index = Lua_Monster::Index(L, 1);
858- monster_data *monster = get_monster_data(monster_index);
859- object_data *object = get_object_data(monster->object_index);
860- int invisible = !lua_toboolean(L, 2);
861- if(monster->action == _monster_is_teleporting_out) return 0;
862- if(MONSTER_IS_ACTIVE(monster) || monster->vitality >= 0) {
863- // Cool stuff happens if you just set an active
864- // monster to invisible. What we should do instead of
865- // the below is expose teleports_out_when_deactivated
866- /*if(invisible) {
867- monster->flags |= (uint16)_monster_teleports_out_when_deactivated;
868- deactivate_monster(monster_index);
869- }*/
870- return luaL_error(L, "visible: monster already activated");
871- }
872- else {
873- // No real possibility of messing stuff up here.
874- SET_OBJECT_INVISIBILITY(object, invisible);
875- }
876- return 0;
877-}
878-
879-static int Lua_Monster_Set_Vitality(lua_State *L)
880-{
881- if (!lua_isnumber(L, 2))
882- return luaL_error(L, "vitality: incorrect argument type");
883-
884- monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
885- monster->vitality = static_cast<int>(lua_tonumber(L, 2));
886- return 0;
887-}
888-
889-const luaL_reg Lua_Monster_Get[] = {
890- {"accelerate", L_TableFunction<Lua_Monster_Accelerate>},
891- {"action", Lua_Monster_Get_Action},
892- {"active", Lua_Monster_Get_Active},
893- {"attack", L_TableFunction<Lua_Monster_Attack>},
894- {"damage", L_TableFunction<Lua_Monster_Damage>},
895- {"external_velocity", Lua_Monster_Get_External_Velocity},
896- {"facing", Lua_Monster_Get_Facing},
897- {"life", Lua_Monster_Get_Vitality},
898- {"mode", Lua_Monster_Get_Mode},
899- {"move_by_path", L_TableFunction<Lua_Monster_Move_By_Path>},
900- {"player", Lua_Monster_Get_Player},
901- {"play_sound", L_TableFunction<Lua_Monster_Play_Sound>},
902- {"polygon", Lua_Monster_Get_Polygon},
903- {"position", L_TableFunction<Lua_Monster_Position>},
904- {"type", Lua_Monster_Get_Type},
905- {"valid", Lua_Monster_Get_Valid},
906- {"vertical_velocity", Lua_Monster_Get_Vertical_Velocity},
907- {"visible", Lua_Monster_Get_Visible},
908- {"vitality", Lua_Monster_Get_Vitality},
909- {"x", Lua_Monster_Get_X},
910- {"y", Lua_Monster_Get_Y},
911- {"yaw", Lua_Monster_Get_Facing},
912- {"z", Lua_Monster_Get_Z},
913- {0, 0}
914-};
915-
916-const luaL_reg Lua_Monster_Set[] = {
917- {"active", Lua_Monster_Set_Active},
918- {"external_velocity", Lua_Monster_Set_External_Velocity},
919- {"facing", Lua_Monster_Set_Facing},
920- {"life", Lua_Monster_Set_Vitality},
921- {"vertical_velocity", Lua_Monster_Set_Vertical_Velocity},
922- {"visible", Lua_Monster_Set_Visible},
923- {"vitality", Lua_Monster_Set_Vitality},
924- {"yaw", Lua_Monster_Set_Facing},
925- {0, 0}
926-};
927-
928-char Lua_Monsters_Name[] = "Monsters";
929-
930-// Monsters.new(x, y, height, polygon, type)
931-int Lua_Monsters_New(lua_State *L)
932-{
933- if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2) || !lua_isnumber(L, 3))
934- luaL_error(L, "new: incorrect argument type");
935-
936- int polygon_index = 0;
937- if (lua_isnumber(L, 4))
938- {
939- polygon_index = static_cast<int>(lua_tonumber(L, 4));
940- if (!Lua_Polygon::Valid(polygon_index))
941- return luaL_error(L, "new: invalid polygon index");
942- }
943- else if (Lua_Polygon::Is(L, 4))
944- {
945- polygon_index = Lua_Polygon::Index(L, 4);
946- }
947- else
948- return luaL_error(L, "new: incorrect argument type");
949-
950- short monster_type = Lua_MonsterType::ToIndex(L, 5);
951-
952- object_location location;
953- location.p.x = static_cast<int>(lua_tonumber(L, 1) * WORLD_ONE);
954- location.p.y = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
955- location.p.z = static_cast<int>(lua_tonumber(L, 3) * WORLD_ONE);
956-
957- location.polygon_index = polygon_index;
958- location.yaw = 0;
959- location.pitch = 0;
960- location.flags = 0;
961-
962- short monster_index = ::new_monster(&location, monster_type);
963- if (monster_index == NONE)
964- return 0;
965-
966- Lua_Monster::Push(L, monster_index);
967- return 1;
968-}
969-
970-const luaL_reg Lua_Monsters_Methods[] = {
971- {"new", Lua_Monsters_New},
972- {0, 0}
973-};
974-
975-static void compatibility(lua_State *L);
976-
977-int Lua_Monsters_register(lua_State *L)
978-{
979- Lua_MonsterClass::Register(L, 0, 0, 0, Lua_MonsterClass_Mnemonics);
980- Lua_MonsterClass::Valid = Lua_MonsterClass_Valid;
981-
982- Lua_MonsterClasses::Register(L);
983- Lua_MonsterClasses::Length = Lua_MonsterClasses::ConstantLength(_class_yeti_bit + 1);
984-
985-
986- Lua_MonsterType_Enemies::Register(L, 0, 0, Lua_MonsterType_Enemies_Metatable);
987- Lua_MonsterType_Friends::Register(L, 0, 0, Lua_MonsterType_Friends_Metatable);
988- Lua_MonsterType_Immunities::Register(L, 0, 0, Lua_MonsterType_Immunities_Metatable);
989- Lua_MonsterType_Weaknesses::Register(L, 0, 0, Lua_MonsterType_Weaknesses_Metatable);
990-
991- Lua_MonsterMode::Register(L, 0, 0, 0, Lua_MonsterMode_Mnemonics);
992- Lua_MonsterMode::Valid = Lua_MonsterMode::ValidRange(NUMBER_OF_MONSTER_MODES);
993- Lua_MonsterModes::Register(L);
994- Lua_MonsterModes::Length = Lua_MonsterModes::ConstantLength(NUMBER_OF_MONSTER_MODES);
995-
996- Lua_MonsterAction::Register(L, 0, 0, 0, Lua_MonsterAction_Mnemonics);
997- Lua_MonsterAction::Valid = Lua_MonsterAction::ValidRange(NUMBER_OF_MONSTER_ACTIONS);
998- Lua_MonsterActions::Register(L);
999- Lua_MonsterActions::Length = Lua_MonsterActions::ConstantLength(NUMBER_OF_MONSTER_ACTIONS);
1000-
1001- Lua_MonsterType::Register(L, Lua_MonsterType_Get, Lua_MonsterType_Set, 0, Lua_MonsterType_Mnemonics);
1002- Lua_MonsterType::Valid = Lua_MonsterType_Valid;
1003-
1004- Lua_MonsterTypes::Register(L);
1005- Lua_MonsterTypes::Length = Lua_MonsterTypes::ConstantLength(NUMBER_OF_MONSTER_TYPES);
1006-
1007- Lua_Monster::Register(L, Lua_Monster_Get, Lua_Monster_Set);
1008- Lua_Monster::Valid = Lua_Monster_Valid;
1009-
1010- Lua_Monsters::Register(L, Lua_Monsters_Methods);
1011- Lua_Monsters::Length = boost::bind(get_dynamic_limit, (int) _dynamic_limit_monsters);
1012-
1013- compatibility(L);
1014- return 0;
1015-}
1016-
1017-static const char *compatibility_script = ""
1018-// there are some conversions to and from internal units, because old
1019-// monster API was wrong
1020- "function activate_monster(monster) Monsters[monster].active = true end\n"
1021- "function attack_monster(agressor, target) Monsters[aggressor]:attack(target) end\n"
1022- "function damage_monster(monster, damage, type) if type then Monsters[monster]:damage(damage, type) else Monsters[monster]:damage(damage) end end\n"
1023- "function deactivate_monster(monster) Monsters[monster].active = false end\n"
1024- "function get_monster_action(monster) if Monsters[monster].action then return Monsters[monster].action.index else return -1 end end\n"
1025- "function get_monster_enemy(monster_type, enemy_type) return MonsterTypes[monster_type].enemies[enemy_type] end\n"
1026- "function get_monster_friend(monster_type, friend_type) return MonsterTypes[monster_type].friends[friend_type] end\n"
1027- "function get_monster_facing(monster) return Monsters[monster].facing * 512 / 360 end\n"
1028- "function get_monster_immunity(monster, damage_type) return MonsterTypes[monster].immunities[damage_type] end\n"
1029- "function get_monster_item(monster) if MonsterTypes[monster].item then return MonsterTypes[monster].item.index else return -1 end end\n"
1030- "function get_monster_mode(monster) if Monsters[monster].mode then return Monsters[monster].mode.index else return -1 end end\n"
1031- "function get_monster_polygon(monster) return Monsters[monster].polygon.index end\n"
1032- "function get_monster_position(monster) return Monsters[monster].x * 1024, Monsters[monster].y * 1024, Monsters[monster].z * 1024 end\n"
1033- "function get_monster_type(monster) return Monsters[monster].type.index end\n"
1034- "function get_monster_type_class(monster) return MonsterTypes[monster].class.index end\n"
1035- "function get_monster_visible(monster) return Monsters[monster].visible end\n"
1036- "function get_monster_vitality(monster) return Monsters[monster].vitality end\n"
1037- "function get_monster_weakness(monster, damage) return MonsterTypes[monster].weaknesses[damage] end\n"
1038- "function monster_index_valid(monster) if Monsters[monster] then return true else return false end end\n"
1039- "function move_monster(monster, polygon) Monsters[monster]:move_by_path(polygon) end\n"
1040- "function new_monster(type, poly, facing, height, x, y) if (x and y) then m = Monsters.new(x, y, height / 1024, poly, type) elseif (height) then m = Monsters.new(Polygons[poly].x, Polygons[poly].y, height / 1024, poly, type) else m = Monsters.new(Polygons[poly].x, Polygons[poly].y, 0, poly, type) end if m then return m.index else return -1 end end\n"
1041- "function set_monster_enemy(monster_type, enemy_type, hostile) MonsterTypes[monster_type].enemies[enemy_type] = hostile end\n"
1042- "function set_monster_friend(monster_type, friend_type, friendly) MonsterTypes[monster_type].friends[friend_type] = friendly end\n"
1043- "function set_monster_immunity(monster, damage, immune) MonsterTypes[monster].immunities[damage] = immune end\n"
1044- "function set_monster_item(monster, item) if item == -1 then MonsterTypes[monster].item = nil else MonsterTypes[monster].item = item end end\n"
1045- "function set_monster_position(monster, polygon, x, y, z) Monsters[monster]:position(x, y, z, polygon) end\n"
1046- "function set_monster_type_class(monster, class) MonsterTypes[monster].class = class end\n"
1047- "function set_monster_vitality(monster, vitality) Monsters[monster].vitality = vitality end\n"
1048- "function set_monster_weakness(monster, damage, weak) MonsterTypes[monster].weaknesses[damage] = weak end\n"
1049- ;
1050-
1051-static void compatibility(lua_State *L)
1052-{
1053- luaL_loadbuffer(L, compatibility_script, strlen(compatibility_script), "monsters_compatibility");
1054- lua_pcall(L, 0, 0, 0);
1055-}
1056-
1057-
1058-
1059-#endif
1+/*
2+LUA_MONSTERS.CPP
3+
4+ Copyright (C) 2008 by Gregory Smith
5+
6+ This program 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+ This program 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+ This license is contained in the file "COPYING",
17+ which is included with this source code; it is available online at
18+ http://www.gnu.org/licenses/gpl.html
19+
20+ Implements the Lua monster classes
21+*/
22+
23+#include "lua_monsters.h"
24+#include "lua_map.h"
25+#include "lua_objects.h"
26+#include "lua_player.h"
27+#include "lua_templates.h"
28+
29+#include "flood_map.h"
30+#include "monsters.h"
31+#include "player.h"
32+
33+#include <boost/bind.hpp>
34+
35+#define DONT_REPEAT_DEFINITIONS
36+#include "monster_definitions.h"
37+
38+#ifdef HAVE_LUA
39+
40+const float AngleConvert = 360/float(FULL_CIRCLE);
41+
42+static inline bool powerOfTwo(int32 x)
43+{
44+ return !((x-1) & x);
45+}
46+
47+char Lua_MonsterClass_Name[] = "monster_class";
48+typedef L_Enum<Lua_MonsterClass_Name, int32> Lua_MonsterClass;
49+
50+bool Lua_MonsterClass_Valid(int32 index)
51+{
52+ return index >= 1 && index <= _class_yeti && powerOfTwo(index);
53+}
54+
55+char Lua_MonsterClasses_Name[] = "MonsterClasses";
56+typedef L_EnumContainer<Lua_MonsterClasses_Name, Lua_MonsterClass> Lua_MonsterClasses;
57+
58+template<>
59+int L_Container<Lua_MonsterClasses_Name, Lua_MonsterClass>::_iterator(lua_State *L)
60+{
61+ int32 index = static_cast<int32>(lua_tonumber(L, lua_upvalueindex(1)));
62+ while (index < Length())
63+ {
64+ if (Lua_MonsterClass::Valid(1 << index))
65+ {
66+ Lua_MonsterClass::Push(L, 1 << index);
67+ lua_pushnumber(L, ++index);
68+ lua_replace(L, lua_upvalueindex(1));
69+ return 1;
70+ }
71+ else
72+ {
73+ ++index;
74+ }
75+ }
76+
77+ lua_pushnil(L);
78+ return 1;
79+}
80+
81+extern object_frequency_definition* monster_placement_info;
82+
83+char Lua_MonsterType_Enemies_Name[] = "monster_type_enemies";
84+typedef L_Class<Lua_MonsterType_Enemies_Name> Lua_MonsterType_Enemies;
85+
86+static int Lua_MonsterType_Enemies_Get(lua_State *L)
87+{
88+ int monster_type = Lua_MonsterType_Enemies::Index(L, 1);
89+ int enemy_class = Lua_MonsterClass::ToIndex(L, 2);
90+
91+ monster_definition *definition = get_monster_definition_external(monster_type);
92+ lua_pushboolean(L, definition->enemies & enemy_class);
93+ return 1;
94+}
95+
96+static int Lua_MonsterType_Enemies_Set(lua_State *L)
97+{
98+ if (!lua_isboolean(L, 3))
99+ return luaL_error(L, "enemies: incorrect argument type");
100+
101+ int monster_type = Lua_MonsterType_Enemies::Index(L, 1);
102+ int enemy_class = Lua_MonsterClass::ToIndex(L, 2);
103+ bool enemy = lua_toboolean(L, 3);
104+ monster_definition *definition = get_monster_definition_external(monster_type);
105+ if (enemy)
106+ {
107+ definition->enemies = definition->enemies | enemy_class;
108+ }
109+ else
110+ {
111+ definition->enemies = definition->enemies & ~(enemy_class);
112+ }
113+
114+ return 0;
115+}
116+
117+const luaL_reg Lua_MonsterType_Enemies_Metatable[] = {
118+ {"__index", Lua_MonsterType_Enemies_Get},
119+ {"__newindex", Lua_MonsterType_Enemies_Set},
120+ {0, 0}
121+};
122+
123+char Lua_MonsterType_Friends_Name[] = "monster_type_friends";
124+typedef L_Class<Lua_MonsterType_Friends_Name> Lua_MonsterType_Friends;
125+
126+static int Lua_MonsterType_Friends_Get(lua_State *L)
127+{
128+ int monster_type = Lua_MonsterType_Friends::Index(L, 1);
129+ int friend_class = Lua_MonsterClass::ToIndex(L, 2);
130+
131+ monster_definition *definition = get_monster_definition_external(monster_type);
132+ lua_pushboolean(L, definition->friends & friend_class);
133+ return 1;
134+}
135+
136+static int Lua_MonsterType_Friends_Set(lua_State *L)
137+{
138+ if (!lua_isboolean(L, 3))
139+ return luaL_error(L, "enemies: incorrect argument type");
140+
141+ int monster_type = Lua_MonsterType_Friends::Index(L, 1);
142+ int friend_class = Lua_MonsterClass::ToIndex(L, 2);
143+ bool friendly = lua_toboolean(L, 3);
144+ monster_definition *definition = get_monster_definition_external(monster_type);
145+ if (friendly)
146+ {
147+ definition->friends = definition->friends | friend_class;
148+ }
149+ else
150+ {
151+ definition->friends = definition->friends & ~(friend_class);
152+ }
153+
154+ return 0;
155+}
156+
157+const luaL_reg Lua_MonsterType_Friends_Metatable[] = {
158+ {"__index", Lua_MonsterType_Friends_Get},
159+ {"__newindex", Lua_MonsterType_Friends_Set},
160+ {0, 0}
161+};
162+
163+char Lua_MonsterType_Immunities_Name[] = "monster_type_immunities";
164+typedef L_Class<Lua_MonsterType_Immunities_Name> Lua_MonsterType_Immunities;
165+
166+static int Lua_MonsterType_Immunities_Get(lua_State *L)
167+{
168+ int monster_type = Lua_MonsterType_Immunities::Index(L, 1);
169+ int damage_type = Lua_DamageType::ToIndex(L, 2);
170+
171+ monster_definition *definition = get_monster_definition_external(monster_type);
172+ lua_pushboolean(L, definition->immunities & (1 << damage_type));
173+ return 1;
174+}
175+
176+static int Lua_MonsterType_Immunities_Set(lua_State *L)
177+{
178+ if (!lua_isboolean(L, 3))
179+ luaL_error(L, "immunities: incorrect argument type");
180+
181+ int monster_type = Lua_MonsterType_Immunities::Index(L, 1);
182+ int damage_type = Lua_DamageType::ToIndex(L, 2);
183+ bool immune = lua_toboolean(L, 3);
184+
185+ monster_definition *definition = get_monster_definition_external(monster_type);
186+ if (immune)
187+ {
188+ definition->immunities |= (1 << damage_type);
189+ }
190+ else
191+ {
192+ definition->immunities &= ~(1 << damage_type);
193+ }
194+
195+ return 0;
196+}
197+
198+const luaL_reg Lua_MonsterType_Immunities_Metatable[] = {
199+ {"__index", Lua_MonsterType_Immunities_Get},
200+ {"__newindex", Lua_MonsterType_Immunities_Set},
201+ {0, 0}
202+};
203+
204+char Lua_MonsterType_Weaknesses_Name[] = "monster_type_weaknesses";
205+typedef L_Class<Lua_MonsterType_Weaknesses_Name> Lua_MonsterType_Weaknesses;
206+
207+int Lua_MonsterType_Weaknesses_Get(lua_State *L)
208+{
209+ int monster_type = Lua_MonsterType_Weaknesses::Index(L, 1);
210+ int damage_type = Lua_DamageType::ToIndex(L, 2);
211+
212+ monster_definition *definition = get_monster_definition_external(monster_type);
213+ lua_pushboolean(L, definition->weaknesses & (1 << damage_type));
214+ return 1;
215+}
216+
217+int Lua_MonsterType_Weaknesses_Set(lua_State *L)
218+{
219+ if (!lua_isboolean(L, 3))
220+ luaL_error(L, "immunities: incorrect argument type");
221+
222+ int monster_type = Lua_MonsterType_Weaknesses::Index(L, 1);
223+ int damage_type = Lua_DamageType::ToIndex(L, 2);
224+ bool weakness = lua_toboolean(L, 3);
225+
226+ monster_definition *definition = get_monster_definition_external(monster_type);
227+ if (weakness)
228+ {
229+ definition->weaknesses |= (1 << damage_type);
230+ }
231+ else
232+ {
233+ definition->weaknesses &= ~(1 << damage_type);
234+ }
235+
236+ return 0;
237+}
238+
239+const luaL_reg Lua_MonsterType_Weaknesses_Metatable[] = {
240+ {"__index", Lua_MonsterType_Weaknesses_Get},
241+ {"__newindex", Lua_MonsterType_Weaknesses_Set},
242+ {0, 0}
243+};
244+
245+char Lua_MonsterType_Name[] = "monster_type";
246+
247+static bool Lua_MonsterType_Valid(int16 index)
248+{
249+ return index >= 0 && index < NUMBER_OF_MONSTER_TYPES;
250+}
251+
252+static int Lua_MonsterType_Get_Class(lua_State *L) {
253+ monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
254+ Lua_MonsterClass::Push(L, definition->_class);
255+ return 1;
256+}
257+
258+static int Lua_MonsterType_Get_Enemies(lua_State *L) {
259+ Lua_MonsterType_Enemies::Push(L, Lua_MonsterType::Index(L, 1));
260+ return 1;
261+}
262+
263+static int Lua_MonsterType_Get_Height(lua_State *L) {
264+ monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
265+ lua_pushnumber(L, (double) definition->height / WORLD_ONE);
266+ return 1;
267+}
268+
269+static int Lua_MonsterType_Get_Friends(lua_State *L) {
270+ Lua_MonsterType_Friends::Push(L, Lua_MonsterType::Index(L, 1));
271+ return 1;
272+}
273+
274+static int Lua_MonsterType_Get_Immunities(lua_State *L) {
275+ Lua_MonsterType_Immunities::Push(L, Lua_MonsterType::Index(L, 1));
276+ return 1;
277+}
278+
279+static int Lua_MonsterType_Get_Impact_Effect(lua_State *L) {
280+ monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
281+ Lua_EffectType::Push(L, definition->impact_effect);
282+ return 1;
283+}
284+
285+static int Lua_MonsterType_Get_Initial_Count(lua_State* L)
286+{
287+ lua_pushnumber(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].initial_count);
288+ return 1;
289+}
290+
291+static int Lua_MonsterType_Get_Maximum_Count(lua_State* L)
292+{
293+ lua_pushnumber(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].maximum_count);
294+ return 1;
295+}
296+
297+
298+static int Lua_MonsterType_Get_Melee_Impact_Effect(lua_State *L) {
299+ monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
300+ Lua_EffectType::Push(L, definition->melee_impact_effect);
301+ return 1;
302+}
303+
304+static int Lua_MonsterType_Get_Minimum_Count(lua_State* L)
305+{
306+ lua_pushnumber(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].minimum_count);
307+ return 1;
308+}
309+
310+static int Lua_MonsterType_Get_Radius(lua_State *L) {
311+ monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
312+ lua_pushnumber(L, (double) definition->radius / WORLD_ONE);
313+ return 1;
314+}
315+
316+static int Lua_MonsterType_Get_Random_Chance(lua_State* L)
317+{
318+ lua_pushnumber(L, (double) monster_placement_info[Lua_MonsterType::Index(L, 1)].random_chance / UINT16_MAX);
319+ return 1;
320+}
321+
322+static int Lua_MonsterType_Get_Random_Count(lua_State* L)
323+{
324+ lua_pushnumber(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].random_count);
325+ return 1;
326+}
327+
328+static int Lua_MonsterType_Get_Random_Location(lua_State* L)
329+{
330+ lua_pushboolean(L, monster_placement_info[Lua_MonsterType::Index(L, 1)].flags & _reappears_in_random_location);
331+ return 1;
332+}
333+
334+static int Lua_MonsterType_Get_Weaknesses(lua_State *L) {
335+ Lua_MonsterType_Weaknesses::Push(L, Lua_MonsterType::Index(L, 1));
336+ return 1;
337+}
338+
339+static int Lua_MonsterType_Get_Item(lua_State *L) {
340+ monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
341+ Lua_ItemType::Push(L, definition->carrying_item_type);
342+ return 1;
343+}
344+
345+static int Lua_MonsterType_Set_Class(lua_State *L) {
346+ monster_definition *definition = get_monster_definition_external(Lua_MonsterType::Index(L, 1));
347+ definition->_class = static_cast<int32>(Lua_MonsterClass::ToIndex(L, 2));
348+ return 0;
349+}
350+
351+static int Lua_MonsterType_Set_Item(lua_State *L) {
352+ int item_type = 0;
353+ if (lua_isnumber(L, 2))
354+ {
355+ item_type = static_cast<int>(lua_tonumber(L, 2));
356+ }
357+ else if (lua_isnil(L, 2))
358+ {
359+ item_type = NONE;
360+ }
361+ else
362+ return luaL_error(L, "item: incorrect argument type");
363+
364+ monster_definition *definition = get_monster_definition_external(Lua_MonsterType::ToIndex(L, 1));
365+
366+ definition->carrying_item_type = item_type;
367+ return 0;
368+}
369+
370+static int Lua_MonsterType_Set_Initial_Count(lua_State* L)
371+{
372+ if (lua_isnumber(L, 2))
373+ {
374+ monster_placement_info[Lua_MonsterType::Index(L, 1)].initial_count = lua_tonumber(L, 2);
375+ }
376+ else
377+ {
378+ return luaL_error(L, "initial_count: incorrect argument type");
379+ }
380+ return 0;
381+}
382+
383+static int Lua_MonsterType_Set_Maximum_Count(lua_State* L)
384+{
385+ if (lua_isnumber(L, 2))
386+ {
387+ monster_placement_info[Lua_MonsterType::Index(L, 1)].maximum_count = lua_tonumber(L, 2);
388+ }
389+ else
390+ {
391+ return luaL_error(L, "maximum_count: incorrect argument type");
392+ }
393+ return 0;
394+}
395+
396+static int Lua_MonsterType_Set_Minimum_Count(lua_State* L)
397+{
398+ if (lua_isnumber(L, 2))
399+ {
400+ monster_placement_info[Lua_MonsterType::Index(L, 1)].minimum_count = lua_tonumber(L, 2);
401+ }
402+ else
403+ {
404+ return luaL_error(L, "minimum_count: incorrect argument type");
405+ }
406+ return 0;
407+}
408+
409+static int Lua_MonsterType_Set_Random_Chance(lua_State* L)
410+{
411+ if (lua_isnumber(L, 2))
412+ {
413+ monster_placement_info[Lua_MonsterType::Index(L, 1)].random_chance = static_cast<uint16>(lua_tonumber(L, 2) * UINT16_MAX + 0.5);
414+ }
415+ else
416+ {
417+ return luaL_error(L, "random_chance: incorrect argument type");
418+ }
419+ return 0;
420+}
421+
422+static int Lua_MonsterType_Set_Random_Count(lua_State* L)
423+{
424+ if (lua_isnumber(L, 2))
425+ {
426+ monster_placement_info[Lua_MonsterType::Index(L, 1)].random_count = lua_tonumber(L, 2);
427+ }
428+ else
429+ {
430+ return luaL_error(L, "random_count: incorrect argument type");
431+ }
432+ return 0;
433+}
434+
435+static int Lua_MonsterType_Set_Random_Location(lua_State* L)
436+{
437+ if (lua_isboolean(L, 2))
438+ {
439+ if (lua_toboolean(L, 2))
440+ {
441+ monster_placement_info[Lua_MonsterType::Index(L, 1)].flags |= _reappears_in_random_location;
442+ }
443+ else
444+ {
445+ monster_placement_info[Lua_MonsterType::Index(L, 1)].flags &= ~_reappears_in_random_location;
446+ }
447+ }
448+ else
449+ {
450+ return luaL_error(L, "random_location: incorrect argument type");
451+ }
452+ return 0;
453+}
454+
455+const luaL_reg Lua_MonsterType_Get[] = {
456+ {"class", Lua_MonsterType_Get_Class},
457+ {"enemies", Lua_MonsterType_Get_Enemies},
458+ {"friends", Lua_MonsterType_Get_Friends},
459+ {"height", Lua_MonsterType_Get_Height},
460+ {"immunities", Lua_MonsterType_Get_Immunities},
461+ {"impact_effect", Lua_MonsterType_Get_Impact_Effect},
462+ {"initial_count", Lua_MonsterType_Get_Initial_Count},
463+ {"maximum_count", Lua_MonsterType_Get_Maximum_Count},
464+ {"melee_impact_effect", Lua_MonsterType_Get_Melee_Impact_Effect},
465+ {"minimum_count", Lua_MonsterType_Get_Minimum_Count},
466+ {"item", Lua_MonsterType_Get_Item},
467+ {"radius", Lua_MonsterType_Get_Radius},
468+ {"random_chance", Lua_MonsterType_Get_Random_Chance},
469+ {"random_location", Lua_MonsterType_Get_Random_Location},
470+ {"total_available", Lua_MonsterType_Get_Random_Count},
471+ {"weaknesses", Lua_MonsterType_Get_Weaknesses},
472+ {0, 0}
473+};
474+
475+const luaL_reg Lua_MonsterType_Set[] = {
476+ {"class", Lua_MonsterType_Set_Class},
477+ {"initial_count", Lua_MonsterType_Set_Initial_Count},
478+ {"item", Lua_MonsterType_Set_Item},
479+ {"maximum_count", Lua_MonsterType_Set_Maximum_Count},
480+ {"minimum_count", Lua_MonsterType_Set_Minimum_Count},
481+ {"random_chance", Lua_MonsterType_Set_Random_Chance},
482+ {"random_location", Lua_MonsterType_Set_Random_Location},
483+ {"total_available", Lua_MonsterType_Set_Random_Count},
484+ {0, 0}
485+};
486+
487+char Lua_MonsterMode_Name[] = "monster_mode";
488+typedef L_Enum<Lua_MonsterMode_Name> Lua_MonsterMode;
489+
490+char Lua_MonsterModes_Name[] = "MonsterModes";
491+typedef L_EnumContainer<Lua_MonsterModes_Name, Lua_MonsterMode> Lua_MonsterModes;
492+
493+char Lua_MonsterAction_Name[] = "monster_action";
494+
495+char Lua_MonsterActions_Name[] = "MonsterActions";
496+typedef L_EnumContainer<Lua_MonsterActions_Name, Lua_MonsterAction> Lua_MonsterActions;
497+
498+char Lua_MonsterTypes_Name[] = "MonsterTypes";
499+typedef L_EnumContainer<Lua_MonsterTypes_Name, Lua_MonsterType> Lua_MonsterTypes;
500+
501+char Lua_Monster_Name[] = "monster";
502+
503+int Lua_Monster_Accelerate(lua_State *L)
504+{
505+ if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4))
506+ return luaL_error(L, "accelerate: incorrect argument type");
507+
508+ short monster_index = Lua_Monster::Index(L, 1);
509+ monster_data *monster = get_monster_data(monster_index);
510+ double direction = static_cast<double>(lua_tonumber(L, 2));
511+ double velocity = static_cast<double>(lua_tonumber(L, 3));
512+ double vertical_velocity = static_cast<double>(lua_tonumber(L, 4));
513+
514+ accelerate_monster(monster_index, static_cast<int>(vertical_velocity * WORLD_ONE), static_cast<int>(direction/AngleConvert), static_cast<int>(velocity * WORLD_ONE));
515+ return 0;
516+}
517+
518+int Lua_Monster_Attack(lua_State *L)
519+{
520+ short target = 0;
521+ if (lua_isnumber(L, 2))
522+ target = static_cast<short>(lua_tonumber(L, 2));
523+ else if (Lua_Monster::Is(L, 2))
524+ target = Lua_Monster::Index(L, 2);
525+ else
526+ return luaL_error(L, "attack: incorrect argument type");
527+
528+ change_monster_target(Lua_Monster::Index(L, 1), target);
529+ return 0;
530+}
531+
532+int Lua_Monster_Play_Sound(lua_State *L)
533+{
534+ short sound_index = Lua_Sound::ToIndex(L, 2);
535+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
536+ play_object_sound(monster->object_index, sound_index);
537+ return 0;
538+}
539+
540+int Lua_Monster_Damage(lua_State *L)
541+{
542+ if (!lua_isnumber(L, 2))
543+ return luaL_error(L, "damage: incorrect argument type");
544+
545+ int damage_amount = static_cast<int>(lua_tonumber(L, 2));
546+ int damage_type = NONE;
547+ if (lua_gettop(L) == 3)
548+ {
549+ damage_type = Lua_DamageType::ToIndex(L, 3);
550+ }
551+
552+ damage_definition damage;
553+ if (damage_type != NONE)
554+ damage.type = damage_type;
555+ else
556+ damage.type = _damage_fist;
557+
558+ damage.base = damage_amount;
559+ damage.random = 0;
560+ damage.flags = 0;
561+ damage.scale = FIXED_ONE;
562+
563+ int monster_index = Lua_Monster::Index(L, 1);
564+ monster_data *monster = get_monster_data(monster_index);
565+ damage_monster(monster_index, NONE, NONE, &(monster->sound_location), &damage, NONE);
566+ return 0;
567+}
568+
569+int Lua_Monster_Valid(int16 index)
570+{
571+ if (index < 0 || index >= MAXIMUM_MONSTERS_PER_MAP)
572+ return false;
573+
574+ monster_data *monster = GetMemberWithBounds(monsters, index, MAXIMUM_MONSTERS_PER_MAP);
575+ return (SLOT_IS_USED(monster));
576+}
577+
578+struct monster_pathfinding_data
579+{
580+ struct monster_definition *definition;
581+ struct monster_data *monster;
582+
583+ bool cross_zone_boundaries;
584+};
585+
586+extern void advance_monster_path(short monster_index);
587+extern int32 monster_pathfinding_cost_function(short source_polygon_index, short line_index, short destination_polygon_index, void *data);
588+extern void set_monster_action(short monster_index, short action);
589+extern void set_monster_mode(short monster_index, short new_mode, short target_index);
590+
591+int Lua_Monster_Move_By_Path(lua_State *L)
592+{
593+ int monster_index = Lua_Monster::Index(L, 1);
594+ int polygon_index = 0;
595+ if (lua_isnumber(L, 2))
596+ {
597+ polygon_index = static_cast<int>(lua_tonumber(L, 2));
598+ if (!Lua_Polygon::Valid(polygon_index))
599+ return luaL_error(L, "move_by_path: invalid polygon index");
600+ }
601+ else if (Lua_Polygon::Is(L, 2))
602+ {
603+ polygon_index = Lua_Polygon::Index(L, 2);
604+ }
605+ else
606+ return luaL_error(L, "move_by_path: incorrect argument type");
607+
608+ monster_data *monster = get_monster_data(monster_index);
609+ if (MONSTER_IS_PLAYER(monster))
610+ return luaL_error(L, "move_by_path: monster is player");
611+
612+ monster_definition *definition = get_monster_definition_external(monster->type);
613+ object_data *object = get_object_data(monster->object_index);
614+ monster_pathfinding_data path;
615+ world_point2d destination;
616+
617+ if (!MONSTER_IS_ACTIVE(monster))
618+ activate_monster(monster_index);
619+
620+ if (monster->path != NONE)
621+ {
622+ delete_path(monster->path);
623+ monster->path = NONE;
624+ }
625+
626+ SET_MONSTER_NEEDS_PATH_STATUS(monster, false);
627+ path.definition = definition;
628+ path.monster = monster;
629+ path.cross_zone_boundaries = true;
630+
631+ destination = get_polygon_data(polygon_index)->center;
632+
633+ monster->path = new_path((world_point2d *) &object->location, object->polygon, &destination, polygon_index, 3 * definition->radius, monster_pathfinding_cost_function, &path);
634+ if (monster->path == NONE)
635+ {
636+ if (monster->action != _monster_is_being_hit || MONSTER_IS_DYING(monster))
637+ {
638+ set_monster_action(monster_index, _monster_is_stationary);
639+ }
640+ set_monster_mode(monster_index, _monster_unlocked, NONE);
641+ return 0;
642+ }
643+
644+ advance_monster_path(monster_index);
645+ return 0;
646+}
647+
648+extern void add_object_to_polygon_object_list(short object_index, short polygon_index);
649+
650+int Lua_Monster_Position(lua_State *L)
651+{
652+ if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4))
653+ return luaL_error(L, "position: incorrect argument type");
654+
655+ short polygon_index = 0;
656+ if (lua_isnumber(L, 5))
657+ {
658+ polygon_index = static_cast<int>(lua_tonumber(L, 5));
659+ if (!Lua_Polygon::Valid(polygon_index))
660+ return luaL_error(L, "position: invalid polygon index");
661+ }
662+ else if (Lua_Polygon::Is(L, 5))
663+ {
664+ polygon_index = Lua_Polygon::Index(L, 5);
665+ }
666+ else
667+ return luaL_error(L, "position: incorrect argument type");
668+
669+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
670+ object_data *object = get_object_data(monster->object_index);
671+ object->location.x = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
672+ object->location.y = static_cast<int>(lua_tonumber(L, 3) * WORLD_ONE);
673+ object->location.z = static_cast<int>(lua_tonumber(L, 4) * WORLD_ONE);
674+
675+ if (polygon_index != object->polygon)
676+ {
677+ remove_object_from_polygon_object_list(monster->object_index);
678+ add_object_to_polygon_object_list(monster->object_index, polygon_index);
679+ }
680+ return 0;
681+}
682+
683+
684+static int Lua_Monster_Get_Action(lua_State *L)
685+{
686+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
687+ Lua_MonsterAction::Push(L, monster->action);
688+ return 1;
689+}
690+
691+static int Lua_Monster_Get_Active(lua_State *L)
692+{
693+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
694+ if (MONSTER_IS_PLAYER(monster))
695+ return luaL_error(L, "active: monster is a player");
696+
697+ lua_pushboolean(L, MONSTER_IS_ACTIVE(monster));
698+ return 1;
699+}
700+
701+static int Lua_Monster_Get_External_Velocity(lua_State *L)
702+{
703+ monster_data* monster = get_monster_data(Lua_Monster::Index(L, 1));
704+ lua_pushnumber(L, (double) monster->external_velocity / WORLD_ONE);
705+ return 1;
706+}
707+
708+static int Lua_Monster_Get_Facing(lua_State *L)
709+{
710+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
711+ object_data *object = get_object_data(monster->object_index);
712+ lua_pushnumber(L, (double) object->facing * AngleConvert);
713+ return 1;
714+}
715+
716+static int Lua_Monster_Get_Mode(lua_State *L)
717+{
718+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
719+ Lua_MonsterMode::Push(L, monster->mode);
720+ return 1;
721+}
722+
723+static int Lua_Monster_Get_Player(lua_State *L)
724+{
725+ int monster_index = Lua_Monster::Index(L, 1);
726+ monster_data *monster = get_monster_data(monster_index);
727+ if (MONSTER_IS_PLAYER(monster))
728+ Lua_Player::Push(L, monster_index_to_player_index(monster_index));
729+ else
730+ lua_pushnil(L);
731+
732+ return 1;
733+}
734+
735+static int Lua_Monster_Get_Polygon(lua_State *L)
736+{
737+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
738+ object_data *object = get_object_data(monster->object_index);
739+ Lua_Polygon::Push(L, object->polygon);
740+ return 1;
741+}
742+
743+static int Lua_Monster_Get_Type(lua_State *L)
744+{
745+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
746+ Lua_MonsterType::Push(L, monster->type);
747+ return 1;
748+}
749+
750+static int Lua_Monster_Get_Valid(lua_State *L)
751+{
752+ lua_pushboolean(L, Lua_Monster::Valid(Lua_Monster::Index(L, 1)));
753+ return 1;
754+}
755+
756+static int Lua_Monster_Get_Vertical_Velocity(lua_State *L)
757+{
758+ monster_data* monster = get_monster_data(Lua_Monster::Index(L, 1));
759+ lua_pushnumber(L, (double) monster->vertical_velocity / WORLD_ONE);
760+ return 1;
761+}
762+
763+static int Lua_Monster_Get_Visible(lua_State *L)
764+{
765+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
766+ object_data *object = get_object_data(monster->object_index);
767+ lua_pushboolean(L, OBJECT_IS_VISIBLE(object));
768+ return 1;
769+}
770+
771+static int Lua_Monster_Get_Vitality(lua_State *L)
772+{
773+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
774+ lua_pushnumber(L, monster->vitality);
775+ return 1;
776+}
777+
778+static int Lua_Monster_Get_X(lua_State *L)
779+{
780+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
781+ object_data *object = get_object_data(monster->object_index);
782+ lua_pushnumber(L, (double) object->location.x / WORLD_ONE);
783+ return 1;
784+}
785+
786+static int Lua_Monster_Get_Y(lua_State *L)
787+{
788+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
789+ object_data *object = get_object_data(monster->object_index);
790+ lua_pushnumber(L, (double) object->location.y / WORLD_ONE);
791+ return 1;
792+}
793+
794+static int Lua_Monster_Get_Z(lua_State *L)
795+{
796+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
797+ object_data *object = get_object_data(monster->object_index);
798+ lua_pushnumber(L, (double) object->location.z / WORLD_ONE);
799+ return 1;
800+}
801+
802+static int Lua_Monster_Set_Active(lua_State *L)
803+{
804+ if (!lua_isboolean(L, 2))
805+ return luaL_error(L, "active: incorrect argument type");
806+
807+ bool activate = lua_toboolean(L, 2);
808+ int monster_index = Lua_Monster::Index(L, 1);
809+ monster_data *monster = get_monster_data(monster_index);
810+ if (MONSTER_IS_PLAYER(monster))
811+ return luaL_error(L, "active: monster is a player");
812+ if (activate)
813+ {
814+ if (!MONSTER_IS_ACTIVE(monster))
815+ activate_monster(monster_index);
816+ }
817+ else
818+ {
819+ if (MONSTER_IS_ACTIVE(monster))
820+ deactivate_monster(monster_index);
821+ }
822+ return 0;
823+}
824+
825+static int Lua_Monster_Set_External_Velocity(lua_State *L)
826+{
827+ if (!lua_isnumber(L, 2))
828+ return luaL_error(L, "external_velocity: incorrect argument type");
829+
830+ monster_data* monster = get_monster_data(Lua_Monster::Index(L, 1));
831+ monster->external_velocity = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
832+ return 0;
833+}
834+
835+static int Lua_Monster_Set_Facing(lua_State *L)
836+{
837+ if (!lua_isnumber(L, 2))
838+ return luaL_error(L, "facing: incorrect argument type");
839+
840+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
841+ object_data *object = get_object_data(monster->object_index);
842+ object->facing = static_cast<int>(lua_tonumber(L, 2) / AngleConvert);
843+ return 0;
844+}
845+
846+static int Lua_Monster_Set_Vertical_Velocity(lua_State *L)
847+{
848+ if (!lua_isnumber(L, 2))
849+ return luaL_error(L, "vertical_velocity: incorrect argument type");
850+
851+ monster_data* monster = get_monster_data(Lua_Monster::Index(L, 1));
852+ monster->vertical_velocity = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
853+ return 0;
854+}
855+
856+static int Lua_Monster_Set_Visible(lua_State *L) {
857+ int monster_index = Lua_Monster::Index(L, 1);
858+ monster_data *monster = get_monster_data(monster_index);
859+ object_data *object = get_object_data(monster->object_index);
860+ int invisible = !lua_toboolean(L, 2);
861+ if(monster->action == _monster_is_teleporting_out) return 0;
862+ if(MONSTER_IS_ACTIVE(monster) || monster->vitality >= 0) {
863+ // Cool stuff happens if you just set an active
864+ // monster to invisible. What we should do instead of
865+ // the below is expose teleports_out_when_deactivated
866+ /*if(invisible) {
867+ monster->flags |= (uint16)_monster_teleports_out_when_deactivated;
868+ deactivate_monster(monster_index);
869+ }*/
870+ return luaL_error(L, "visible: monster already activated");
871+ }
872+ else {
873+ // No real possibility of messing stuff up here.
874+ SET_OBJECT_INVISIBILITY(object, invisible);
875+ }
876+ return 0;
877+}
878+
879+static int Lua_Monster_Set_Vitality(lua_State *L)
880+{
881+ if (!lua_isnumber(L, 2))
882+ return luaL_error(L, "vitality: incorrect argument type");
883+
884+ monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
885+ monster->vitality = static_cast<int>(lua_tonumber(L, 2));
886+ return 0;
887+}
888+
889+const luaL_reg Lua_Monster_Get[] = {
890+ {"accelerate", L_TableFunction<Lua_Monster_Accelerate>},
891+ {"action", Lua_Monster_Get_Action},
892+ {"active", Lua_Monster_Get_Active},
893+ {"attack", L_TableFunction<Lua_Monster_Attack>},
894+ {"damage", L_TableFunction<Lua_Monster_Damage>},
895+ {"external_velocity", Lua_Monster_Get_External_Velocity},
896+ {"facing", Lua_Monster_Get_Facing},
897+ {"life", Lua_Monster_Get_Vitality},
898+ {"mode", Lua_Monster_Get_Mode},
899+ {"move_by_path", L_TableFunction<Lua_Monster_Move_By_Path>},
900+ {"player", Lua_Monster_Get_Player},
901+ {"play_sound", L_TableFunction<Lua_Monster_Play_Sound>},
902+ {"polygon", Lua_Monster_Get_Polygon},
903+ {"position", L_TableFunction<Lua_Monster_Position>},
904+ {"type", Lua_Monster_Get_Type},
905+ {"valid", Lua_Monster_Get_Valid},
906+ {"vertical_velocity", Lua_Monster_Get_Vertical_Velocity},
907+ {"visible", Lua_Monster_Get_Visible},
908+ {"vitality", Lua_Monster_Get_Vitality},
909+ {"x", Lua_Monster_Get_X},
910+ {"y", Lua_Monster_Get_Y},
911+ {"yaw", Lua_Monster_Get_Facing},
912+ {"z", Lua_Monster_Get_Z},
913+ {0, 0}
914+};
915+
916+const luaL_reg Lua_Monster_Set[] = {
917+ {"active", Lua_Monster_Set_Active},
918+ {"external_velocity", Lua_Monster_Set_External_Velocity},
919+ {"facing", Lua_Monster_Set_Facing},
920+ {"life", Lua_Monster_Set_Vitality},
921+ {"vertical_velocity", Lua_Monster_Set_Vertical_Velocity},
922+ {"visible", Lua_Monster_Set_Visible},
923+ {"vitality", Lua_Monster_Set_Vitality},
924+ {"yaw", Lua_Monster_Set_Facing},
925+ {0, 0}
926+};
927+
928+char Lua_Monsters_Name[] = "Monsters";
929+
930+// Monsters.new(x, y, height, polygon, type)
931+int Lua_Monsters_New(lua_State *L)
932+{
933+ if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2) || !lua_isnumber(L, 3))
934+ luaL_error(L, "new: incorrect argument type");
935+
936+ int polygon_index = 0;
937+ if (lua_isnumber(L, 4))
938+ {
939+ polygon_index = static_cast<int>(lua_tonumber(L, 4));
940+ if (!Lua_Polygon::Valid(polygon_index))
941+ return luaL_error(L, "new: invalid polygon index");
942+ }
943+ else if (Lua_Polygon::Is(L, 4))
944+ {
945+ polygon_index = Lua_Polygon::Index(L, 4);
946+ }
947+ else
948+ return luaL_error(L, "new: incorrect argument type");
949+
950+ short monster_type = Lua_MonsterType::ToIndex(L, 5);
951+
952+ object_location location;
953+ location.p.x = static_cast<int>(lua_tonumber(L, 1) * WORLD_ONE);
954+ location.p.y = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
955+ location.p.z = static_cast<int>(lua_tonumber(L, 3) * WORLD_ONE);
956+
957+ location.polygon_index = polygon_index;
958+ location.yaw = 0;
959+ location.pitch = 0;
960+ location.flags = 0;
961+
962+ short monster_index = ::new_monster(&location, monster_type);
963+ if (monster_index == NONE)
964+ return 0;
965+
966+ Lua_Monster::Push(L, monster_index);
967+ return 1;
968+}
969+
970+const luaL_reg Lua_Monsters_Methods[] = {
971+ {"new", Lua_Monsters_New},
972+ {0, 0}
973+};
974+
975+static void compatibility(lua_State *L);
976+
977+int Lua_Monsters_register(lua_State *L)
978+{
979+ Lua_MonsterClass::Register(L, 0, 0, 0, Lua_MonsterClass_Mnemonics);
980+ Lua_MonsterClass::Valid = Lua_MonsterClass_Valid;
981+
982+ Lua_MonsterClasses::Register(L);
983+ Lua_MonsterClasses::Length = Lua_MonsterClasses::ConstantLength(_class_yeti_bit + 1);
984+
985+
986+ Lua_MonsterType_Enemies::Register(L, 0, 0, Lua_MonsterType_Enemies_Metatable);
987+ Lua_MonsterType_Friends::Register(L, 0, 0, Lua_MonsterType_Friends_Metatable);
988+ Lua_MonsterType_Immunities::Register(L, 0, 0, Lua_MonsterType_Immunities_Metatable);
989+ Lua_MonsterType_Weaknesses::Register(L, 0, 0, Lua_MonsterType_Weaknesses_Metatable);
990+
991+ Lua_MonsterMode::Register(L, 0, 0, 0, Lua_MonsterMode_Mnemonics);
992+ Lua_MonsterMode::Valid = Lua_MonsterMode::ValidRange(NUMBER_OF_MONSTER_MODES);
993+ Lua_MonsterModes::Register(L);
994+ Lua_MonsterModes::Length = Lua_MonsterModes::ConstantLength(NUMBER_OF_MONSTER_MODES);
995+
996+ Lua_MonsterAction::Register(L, 0, 0, 0, Lua_MonsterAction_Mnemonics);
997+ Lua_MonsterAction::Valid = Lua_MonsterAction::ValidRange(NUMBER_OF_MONSTER_ACTIONS);
998+ Lua_MonsterActions::Register(L);
999+ Lua_MonsterActions::Length = Lua_MonsterActions::ConstantLength(NUMBER_OF_MONSTER_ACTIONS);
1000+
1001+ Lua_MonsterType::Register(L, Lua_MonsterType_Get, Lua_MonsterType_Set, 0, Lua_MonsterType_Mnemonics);
1002+ Lua_MonsterType::Valid = Lua_MonsterType_Valid;
1003+
1004+ Lua_MonsterTypes::Register(L);
1005+ Lua_MonsterTypes::Length = Lua_MonsterTypes::ConstantLength(NUMBER_OF_MONSTER_TYPES);
1006+
1007+ Lua_Monster::Register(L, Lua_Monster_Get, Lua_Monster_Set);
1008+ Lua_Monster::Valid = Lua_Monster_Valid;
1009+
1010+ Lua_Monsters::Register(L, Lua_Monsters_Methods);
1011+ Lua_Monsters::Length = boost::bind(get_dynamic_limit, (int) _dynamic_limit_monsters);
1012+
1013+ compatibility(L);
1014+ return 0;
1015+}
1016+
1017+static const char *compatibility_script = ""
1018+// there are some conversions to and from internal units, because old
1019+// monster API was wrong
1020+ "function activate_monster(monster) Monsters[monster].active = true end\n"
1021+ "function attack_monster(agressor, target) Monsters[aggressor]:attack(target) end\n"
1022+ "function damage_monster(monster, damage, type) if type then Monsters[monster]:damage(damage, type) else Monsters[monster]:damage(damage) end end\n"
1023+ "function deactivate_monster(monster) Monsters[monster].active = false end\n"
1024+ "function get_monster_action(monster) if Monsters[monster].action then return Monsters[monster].action.index else return -1 end end\n"
1025+ "function get_monster_enemy(monster_type, enemy_type) return MonsterTypes[monster_type].enemies[enemy_type] end\n"
1026+ "function get_monster_friend(monster_type, friend_type) return MonsterTypes[monster_type].friends[friend_type] end\n"
1027+ "function get_monster_facing(monster) return Monsters[monster].facing * 512 / 360 end\n"
1028+ "function get_monster_immunity(monster, damage_type) return MonsterTypes[monster].immunities[damage_type] end\n"
1029+ "function get_monster_item(monster) if MonsterTypes[monster].item then return MonsterTypes[monster].item.index else return -1 end end\n"
1030+ "function get_monster_mode(monster) if Monsters[monster].mode then return Monsters[monster].mode.index else return -1 end end\n"
1031+ "function get_monster_polygon(monster) return Monsters[monster].polygon.index end\n"
1032+ "function get_monster_position(monster) return Monsters[monster].x * 1024, Monsters[monster].y * 1024, Monsters[monster].z * 1024 end\n"
1033+ "function get_monster_type(monster) return Monsters[monster].type.index end\n"
1034+ "function get_monster_type_class(monster) return MonsterTypes[monster].class.index end\n"
1035+ "function get_monster_visible(monster) return Monsters[monster].visible end\n"
1036+ "function get_monster_vitality(monster) return Monsters[monster].vitality end\n"
1037+ "function get_monster_weakness(monster, damage) return MonsterTypes[monster].weaknesses[damage] end\n"
1038+ "function monster_index_valid(monster) if Monsters[monster] then return true else return false end end\n"
1039+ "function move_monster(monster, polygon) Monsters[monster]:move_by_path(polygon) end\n"
1040+ "function new_monster(type, poly, facing, height, x, y) if (x and y) then m = Monsters.new(x, y, height / 1024, poly, type) elseif (height) then m = Monsters.new(Polygons[poly].x, Polygons[poly].y, height / 1024, poly, type) else m = Monsters.new(Polygons[poly].x, Polygons[poly].y, 0, poly, type) end if m then return m.index else return -1 end end\n"
1041+ "function set_monster_enemy(monster_type, enemy_type, hostile) MonsterTypes[monster_type].enemies[enemy_type] = hostile end\n"
1042+ "function set_monster_friend(monster_type, friend_type, friendly) MonsterTypes[monster_type].friends[friend_type] = friendly end\n"
1043+ "function set_monster_immunity(monster, damage, immune) MonsterTypes[monster].immunities[damage] = immune end\n"
1044+ "function set_monster_item(monster, item) if item == -1 then MonsterTypes[monster].item = nil else MonsterTypes[monster].item = item end end\n"
1045+ "function set_monster_position(monster, polygon, x, y, z) Monsters[monster]:position(x, y, z, polygon) end\n"
1046+ "function set_monster_type_class(monster, class) MonsterTypes[monster].class = class end\n"
1047+ "function set_monster_vitality(monster, vitality) Monsters[monster].vitality = vitality end\n"
1048+ "function set_monster_weakness(monster, damage, weak) MonsterTypes[monster].weaknesses[damage] = weak end\n"
1049+ ;
1050+
1051+static void compatibility(lua_State *L)
1052+{
1053+ luaL_loadbuffer(L, compatibility_script, strlen(compatibility_script), "monsters_compatibility");
1054+ lua_pcall(L, 0, 0, 0);
1055+}
1056+
1057+
1058+
1059+#endif
--- marathon/trunk/Source_Files/RenderOther/FontHandler.h (revision 507)
+++ marathon/trunk/Source_Files/RenderOther/FontHandler.h (revision 508)
@@ -1,186 +1,189 @@
1-#ifndef _FONT_HANDLER_
2-#define _FONT_HANDLER_
3-
4-/*
5-
6- Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
7- and the "Aleph One" developers.
8-
9- This program is free software; you can redistribute it and/or modify
10- it under the terms of the GNU General Public License as published by
11- the Free Software Foundation; either version 3 of the License, or
12- (at your option) any later version.
13-
14- This program is distributed in the hope that it will be useful,
15- but WITHOUT ANY WARRANTY; without even the implied warranty of
16- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17- GNU General Public License for more details.
18-
19- This license is contained in the file "COPYING",
20- which is included with this source code; it is available online at
21- http://www.gnu.org/licenses/gpl.html
22-
23- Font handler
24- by Loren Petrich,
25- December 17, 2000
26-
27- This is for specifying and working with text fonts;
28- specifying them, changing them with XML, and creating a font brush
29- for OpenGL rendering
30-
31-Jan 5, 2001 (Loren Petrich):
32- Added a "file" field, for containing font filenames
33-
34-Jan 14, 2001 (Loren Petrich):
35- Removed the style definitions; will use styleNormal, styleBold, etc. from csfonts.h
36-*/
37-
38-
39-#include "cseries.h"
40-#include "XML_ElementParser.h"
41-
42-#if defined(SDL)
43-#include "sdl_fonts.h"
44-#endif
45-
46-#ifdef HAVE_OPENGL
47-#include "OGL_Headers.h"
48-#endif
49-
50-#include <set>
51-
52-struct screen_rectangle;
53-
54-class FontSpecifier;
55-
56-class FontSpecifier
57-{
58-public:
59- enum {
60- // How many characters
61- NameSetLen = 64
62- };
63-
64- // Parameters:
65-
66- // Name in HTML-fontname style "font1, font2, font3";
67- // use the first of these fonts that are present,
68- // otherwise use some sensible default
69- char NameSet[NameSetLen];
70- short Size;
71- short Style;
72- short AdjustLineHeight;
73-
74- // For SDL font support: a font filename
75- char File[NameSetLen];
76-
77- // Derived quantities: sync with parameters by calling Update()
78- short Height; // How tall is it?
79- short LineSpacing; // From same positions in each line
80- short Ascent, Descent, Leading;
81- short Widths[256];
82-
83- // MacOS- and SDL-specific stuff
84-#if defined(mac)
85- short ID;
86-#elif defined(SDL)
87- font_info *Info;
88-#endif
89-
90- // Initialize: call this before calling anything else;
91- // this is from not having a proper constructor for this object.
92- void Init();
93-
94- // Do the updating: must be called before using the font; however, it is called by Init(),
95- // and it will be called by the XML parser if it updates the parameters
96- void Update();
97-
98- // Use this font (MacOS-specific); has this form because MacOS Quickdraw has a global font value
99- // for each GrafPort (draw context)
100-#ifdef mac
101- void Use();
102-#endif
103-
104- // Get text width for text that must be centered (map title)
105- int TextWidth(const char *Text);
106-
107- // Get width of one character
108- int CharWidth(char c) const { return Widths[static_cast<int>(c)]; }
109-
110-#ifdef HAVE_OPENGL
111- // Reset the OpenGL fonts; its arg indicates whether this is for starting an OpenGL session
112- // (this is to avoid texture and display-list memory leaks and other such things)
113- void OGL_Reset(bool IsStarting);
114-
115- // Renders a C-style string in OpenGL.
116- // assumes screen coordinates and that the left baseline point is at (0,0).
117- // Alters the modelview matrix so that the next characters will be drawn at the proper place.
118- // One can surround it with glPushMatrix() and glPopMatrix() to remember the original.
119- void OGL_Render(const char *Text);
120-
121- // Renders text a la _draw_screen_text() (see screen_drawing.h), with
122- // alignment and wrapping. Modelview matrix is unaffected.
123- void OGL_DrawText(const char *Text, const screen_rectangle &r, short flags);
124-
125- // Calls OGL_Reset() on all fonts. This is used when the OpenGL context
126- // is changing, so that textures and display lists are cleaned up.
127- static void OGL_ResetFonts(bool IsStarting);
128-
129- // Add or remove an instance from the registry of in-use OpenGL fonts.
130- // To recycle OpenGL assets properly on context switches, the set
131- // m_font_registry tracks all active fonts.
132- static void OGL_Register(FontSpecifier *F);
133- static void OGL_Deregister(FontSpecifier *F);
134-
135-#endif
136-
137- // Draw text without worrying about OpenGL vs. SDL mode.
138- int DrawText(SDL_Surface *s, const char *text, int x, int y, uint32 pixel, bool utf8 = false);
139-
140- ~FontSpecifier();
141-
142- // Equality and assignment operators
143- bool operator==(FontSpecifier& F);
144- bool operator!=(FontSpecifier& F)
145- {return (!((*this) == F));}
146- FontSpecifier& operator=(FontSpecifier& F);
147-
148- // Search functions for names; call these in alternation on a pointer to the current name,
149- // which is initialized to the name-string pointer above
150-
151- // Given a pointer to somewhere in a name set, returns the pointer
152- // to the start of the next name, or NULL if it did not find any
153- static char *FindNextName(char *NamePtr);
154-
155- // Given a pointer to the beginning of a name, finds the pointer to the character
156- // just after the end of that name
157- static char *FindNameEnd(char *NamePtr);
158-
159- // Not sure what kind of explicit constructor would be consistent with the way
160- // that fonts' initial values are specified, as {nameset-string, size, style}.
161- // Also, private members are inconsistent with that sort of initialization.
162-
163-#ifdef HAVE_OPENGL
164- // Stuff for OpenGL font rendering: the font texture and a display list for font rendering;
165- // if OGL_Texture is NULL, then there is no OpenGL font texture to render.
166- uint8 *OGL_Texture;
167- short TxtrWidth, TxtrHeight;
168- int GetTxtrSize() {return int(TxtrWidth)*int(TxtrHeight);}
169- GLuint TxtrID;
170- uint32 DispList;
171- static set<FontSpecifier*> *m_font_registry;
172-#endif
173-};
174-
175-
176-// Returns a parser for the fonts;
177-// several elements may have colors, so this ought to be callable several times.
178-XML_ElementParser *Font_GetParser();
179-
180-// This sets the list of fonts to be read into.
181-// Its args are the pointer to that list and the number of fonts in it.
182-// If that number is <= 0, then the color value is assumed to be non-indexed,
183-// and no "index" attribute will be searched for.
184-void Font_SetArray(FontSpecifier *FontList, int NumColors = 0);
185-
186-#endif
1+#ifndef _FONT_HANDLER_
2+#define _FONT_HANDLER_
3+
4+/*
5+
6+ Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
7+ and the "Aleph One" developers.
8+
9+ This program is free software; you can redistribute it and/or modify
10+ it under the terms of the GNU General Public License as published by
11+ the Free Software Foundation; either version 3 of the License, or
12+ (at your option) any later version.
13+
14+ This program is distributed in the hope that it will be useful,
15+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+ GNU General Public License for more details.
18+
19+ This license is contained in the file "COPYING",
20+ which is included with this source code; it is available online at
21+ http://www.gnu.org/licenses/gpl.html
22+
23+ Font handler
24+ by Loren Petrich,
25+ December 17, 2000
26+
27+ This is for specifying and working with text fonts;
28+ specifying them, changing them with XML, and creating a font brush
29+ for OpenGL rendering
30+
31+Jan 5, 2001 (Loren Petrich):
32+ Added a "file" field, for containing font filenames
33+
34+Jan 14, 2001 (Loren Petrich):
35+ Removed the style definitions; will use styleNormal, styleBold, etc. from csfonts.h
36+*/
37+
38+
39+#include "cseries.h"
40+#include "XML_ElementParser.h"
41+
42+#if defined(SDL)
43+#include "sdl_fonts.h"
44+#endif
45+
46+#ifdef HAVE_OPENGL
47+#include "OGL_Headers.h"
48+#endif
49+
50+#include <set>
51+#include <string>
52+#include <boost/unordered_map.hpp>
53+struct screen_rectangle;
54+
55+class FontSpecifier;
56+
57+class FontSpecifier
58+{
59+public:
60+ enum {
61+ // How many characters
62+ NameSetLen = 64
63+ };
64+
65+ // Parameters:
66+
67+ // Name in HTML-fontname style "font1, font2, font3";
68+ // use the first of these fonts that are present,
69+ // otherwise use some sensible default
70+ char NameSet[NameSetLen];
71+ short Size;
72+ short Style;
73+ short AdjustLineHeight;
74+
75+ // For SDL font support: a font filename
76+ char File[NameSetLen];
77+
78+ // Derived quantities: sync with parameters by calling Update()
79+ short Height; // How tall is it?
80+ short LineSpacing; // From same positions in each line
81+ short Ascent, Descent, Leading;
82+ short Widths[256];
83+
84+ // MacOS- and SDL-specific stuff
85+#if defined(mac)
86+ short ID;
87+#elif defined(SDL)
88+ font_info *Info;
89+#endif
90+
91+ // Initialize: call this before calling anything else;
92+ // this is from not having a proper constructor for this object.
93+ void Init();
94+
95+ // Do the updating: must be called before using the font; however, it is called by Init(),
96+ // and it will be called by the XML parser if it updates the parameters
97+ void Update();
98+
99+ // Use this font (MacOS-specific); has this form because MacOS Quickdraw has a global font value
100+ // for each GrafPort (draw context)
101+#ifdef mac
102+ void Use();
103+#endif
104+
105+ // Get text width for text that must be centered (map title)
106+ int TextWidth(const char *Text);
107+
108+ // Get width of one character
109+ int CharWidth(char c) const { return Widths[static_cast<int>(c)]; }
110+
111+#ifdef HAVE_OPENGL
112+ // Reset the OpenGL fonts; its arg indicates whether this is for starting an OpenGL session
113+ // (this is to avoid texture and display-list memory leaks and other such things)
114+ void OGL_Reset(bool IsStarting);
115+
116+ // Renders a C-style string in OpenGL.
117+ // assumes screen coordinates and that the left baseline point is at (0,0).
118+ // Alters the modelview matrix so that the next characters will be drawn at the proper place.
119+ // One can surround it with glPushMatrix() and glPopMatrix() to remember the original.
120+ void OGL_Render(const char *Text);
121+
122+ // Renders text a la _draw_screen_text() (see screen_drawing.h), with
123+ // alignment and wrapping. Modelview matrix is unaffected.
124+ void OGL_DrawText(const char *Text, const screen_rectangle &r, short flags);
125+
126+ // Calls OGL_Reset() on all fonts. This is used when the OpenGL context
127+ // is changing, so that textures and display lists are cleaned up.
128+ static void OGL_ResetFonts(bool IsStarting);
129+
130+ // Add or remove an instance from the registry of in-use OpenGL fonts.
131+ // To recycle OpenGL assets properly on context switches, the set
132+ // m_font_registry tracks all active fonts.
133+ static void OGL_Register(FontSpecifier *F);
134+ static void OGL_Deregister(FontSpecifier *F);
135+
136+#endif
137+
138+ // Draw text without worrying about OpenGL vs. SDL mode.
139+ int DrawText(SDL_Surface *s, const char *text, int x, int y, uint32 pixel, bool utf8 = false);
140+
141+ ~FontSpecifier();
142+
143+ // Equality and assignment operators
144+ bool operator==(FontSpecifier& F);
145+ bool operator!=(FontSpecifier& F)
146+ {return (!((*this) == F));}
147+ FontSpecifier& operator=(FontSpecifier& F);
148+
149+ // Search functions for names; call these in alternation on a pointer to the current name,
150+ // which is initialized to the name-string pointer above
151+
152+ // Given a pointer to somewhere in a name set, returns the pointer
153+ // to the start of the next name, or NULL if it did not find any
154+ static char *FindNextName(char *NamePtr);
155+
156+ // Given a pointer to the beginning of a name, finds the pointer to the character
157+ // just after the end of that name
158+ static char *FindNameEnd(char *NamePtr);
159+
160+ // Not sure what kind of explicit constructor would be consistent with the way
161+ // that fonts' initial values are specified, as {nameset-string, size, style}.
162+ // Also, private members are inconsistent with that sort of initialization.
163+
164+#ifdef HAVE_OPENGL
165+ // Stuff for OpenGL font rendering: the font texture and a display list for font rendering;
166+ // if OGL_Texture is NULL, then there is no OpenGL font texture to render.
167+ void render_text_(int n, const char* str);
168+ uint8 *OGL_Texture[256];
169+ short TxtrWidth[256], TxtrHeight[256];
170+ int GetTxtrSize(int m) {return int(TxtrWidth[m])*int(TxtrHeight[m]);}
171+ GLuint TxtrID[256];
172+ uint32 DispList;
173+ boost::unordered_map<std::string, int> textMap;
174+ static set<FontSpecifier*> *m_font_registry;
175+#endif
176+};
177+
178+
179+// Returns a parser for the fonts;
180+// several elements may have colors, so this ought to be callable several times.
181+XML_ElementParser *Font_GetParser();
182+
183+// This sets the list of fonts to be read into.
184+// Its args are the pointer to that list and the number of fonts in it.
185+// If that number is <= 0, then the color value is assumed to be non-indexed,
186+// and no "index" attribute will be searched for.
187+void Font_SetArray(FontSpecifier *FontList, int NumColors = 0);
188+
189+#endif
--- marathon/trunk/Source_Files/RenderOther/FontHandler.cpp (revision 507)
+++ marathon/trunk/Source_Files/RenderOther/FontHandler.cpp (revision 508)
@@ -10,7 +10,7 @@
1010
1111 This program is distributed in the hope that it will be useful,
1212 but WITHOUT ANY WARRANTY; without even the implied warranty of
13- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414 GNU General Public License for more details.
1515
1616 This license is contained in the file "COPYING",
@@ -35,7 +35,7 @@
3535 */
3636
3737 #include "cseries.h"
38-
38+#include <stdio.h>
3939 #ifdef __MVCPP__
4040 #include <windows.h>
4141 #endif
@@ -95,7 +95,9 @@
9595 #endif
9696 Update();
9797 #ifdef HAVE_OPENGL
98- OGL_Texture = NULL;
98+ for(int n = 0; n < 256; ++n ) {
99+ OGL_Texture[n] = NULL;
100+ }
99101 #endif
100102 }
101103
@@ -211,7 +213,7 @@
211213 Spec.size = Size;
212214 Spec.style = Style;
213215 Spec.adjust_height = AdjustLineHeight;
214-// Spec.normal = "mono";
216+// Spec.normal = "mono";
215217 Info = load_font(Spec);
216218
217219 if (Info) {
@@ -231,272 +233,135 @@
231233
232234 int FontSpecifier::TextWidth(const char *text)
233235 {
234-#if 0
235- int width = 0;
236- char c;
237- while ((c = *text++) != 0)
238- width += Widths[c];
239- return width;
240-#else
241236 // Japaneese font(assume text is shiftjis)
242237 return Info->text_width(text, 0,false);
243-#endif
244238 }
245239
246240 #endif
247241
248242 #ifdef HAVE_OPENGL
249-// Reset the OpenGL fonts; its arg indicates whether this is for starting an OpenGL session
250-// (this is to avoid texture and display-list memory leaks and other such things)
251-void FontSpecifier::OGL_Reset(bool IsStarting)
252-{
253-#if 0
254- // Don't delete these if there is no valid texture;
255- // that indicates that there are no valid texture and display-list ID's.
256- if (!IsStarting && OGL_Texture)
257- {
258- glDeleteTextures(1,&TxtrID);
259- glDeleteLists(DispList,256);
260- OGL_Deregister(this);
261- }
262-
263- // Invalidates whatever texture had been present
264- if (OGL_Texture)
265- {
266- delete[]OGL_Texture;
267- OGL_Texture = NULL;
268- }
269-
270- if (!IsStarting)
271- return;
272-
273- // Put some padding around each glyph so as to avoid clipping it
243+void FontSpecifier::render_text_(int n, const char* str) {
244+ if( OGL_Texture[n] )
245+ return;
246+ // Put some padding around each glyph so as to avoid clipping i
274247 const int Pad = 1;
275- int ascent_p = Ascent + Pad, descent_p = Descent + Pad;
276- int widths_p[256];
277- for (int i=0; i<256; i++) {
278- widths_p[i] = Widths[i] + 2*Pad;
279- }
280- // Now for the totals and dimensions
281- int TotalWidth = 0;
282- for (int k=0; k<256; k++)
283- TotalWidth += widths_p[k];
284-
285- // For an empty font, clear out
286- if (TotalWidth <= 0) return;
287-
248+ int ascent_p = Ascent + Pad, descent_p = Descent + Pad;
288249 int GlyphHeight = ascent_p + descent_p;
289-
290- int EstDim = int(sqrt(static_cast<float>(TotalWidth*GlyphHeight)) + 0.5);
291- TxtrWidth = MAX(128, NextPowerOfTwo(EstDim));
292-
250+
251+ int TotalWidth = TextWidth(str)+Pad*2;
252+ Widths[n] = TotalWidth;
253+ TxtrWidth[n] = MAX(64, NextPowerOfTwo(TotalWidth));
254+
293255 // Find the character starting points and counts
294- unsigned char CharStarts[256], CharCounts[256];
295- int LastLine = 0;
296- CharStarts[LastLine] = 0;
297- CharCounts[LastLine] = 0;
298- short Pos = 0;
299- for (int k=0; k<256; k++)
300- {
301- // Over the edge? If so, then start a new line
302- short NewPos = Pos + widths_p[k];
303- if (NewPos > TxtrWidth)
304- {
305- LastLine++;
306- CharStarts[LastLine] = k;
307- Pos = widths_p[k];
308- CharCounts[LastLine] = 1;
309- } else {
310- Pos = NewPos;
311- CharCounts[LastLine]++;
312- }
313- }
314- TxtrHeight = MAX(128, NextPowerOfTwo(GlyphHeight*(LastLine+1)));
315-
316-#if defined(mac)
256+ TxtrHeight[n] = MAX(64, NextPowerOfTwo(GlyphHeight));
317257
318- // MacOS-specific: render the font glyphs onto a GWorld,
319- // and use it as the source of the font texture.
320- Rect ImgRect;
321- SetRect(&ImgRect,0,0,TxtrWidth,TxtrHeight);
322- GWorldPtr FTGW;
323- OSErr Err = NewGWorld(&FTGW,32,&ImgRect,0,0,0);
324- if (Err != noErr) return;
325- PixMapHandle Pxls = GetGWorldPixMap(FTGW);
326- LockPixels(Pxls);
327-
328- CGrafPtr OrigPort;
329- GDHandle OrigDevice;
330- GetGWorld(&OrigPort,&OrigDevice);
331- SetGWorld(FTGW,0);
332-
333- BackColor(blackColor);
334- ForeColor(whiteColor);
335- EraseRect(&ImgRect);
336-
337- Use(); // The GWorld needs its font set for it
338-
339- for (int k=0; k<=LastLine; k++)
340- {
341- char Which = CharStarts[k];
342- int VPos = k*GlyphHeight + ascent_p;
343- int HPos = Pad;
344- for (int m=0; m<CharCounts[k]; m++)
345- {
346- MoveTo(HPos,VPos);
347- DrawChar(Which);
348- HPos += widths_p[(unsigned char) (Which++)];
349- }
350- }
351-
352-#elif defined(SDL)
258+
353259 // Render the font glyphs into the SDL surface
354- SDL_Surface *FontSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, TxtrWidth, TxtrHeight, 32, 0xff0000, 0x00ff00, 0x0000ff, 0);
355- if (FontSurface == NULL)
260+ SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, TxtrWidth[n], TxtrHeight[n], 32, 0xff0000, 0x00ff00, 0x0000ff, 0);
261+ if (s == NULL)
356262 return;
357-
358263 // Set background to black
359- SDL_FillRect(FontSurface, NULL, SDL_MapRGB(FontSurface->format, 0, 0, 0));
360- Uint32 White = SDL_MapRGB(FontSurface->format, 0xFF, 0xFF, 0xFF);
361-
264+ SDL_FillRect(s, NULL, SDL_MapRGB(s->format, 0, 0, 0));
265+ Uint32 White = SDL_MapRGB(s->format, 0xFF, 0xFF, 0xFF);
266+
362267 // Copy to surface
363- for (int k = 0; k <= LastLine; k++)
268+ ::draw_text(s, str, strlen(str), 1, ascent_p, White, Info, Style);
269+
270+ OGL_Texture[n] = new uint8[GetTxtrSize(n)*2];
271+ // Copy the SDL surface into the OpenGL texture
272+ uint8 *PixBase = (uint8 *)s->pixels;
273+ int Stride = s->pitch;
274+
275+ for (int k=0; k<TxtrHeight[n]; k++)
364276 {
365- char Which = CharStarts[k];
366- int VPos = (k * GlyphHeight) + ascent_p;
367- int HPos = Pad;
368- for (int m = 0; m < CharCounts[k]; m++)
277+ uint8 *SrcPxl = PixBase + k*Stride + 1; // Use one of the middle channels (red or green or blue)
278+ uint8 *DstPxl = OGL_Texture[n] + 2*k*TxtrWidth[n];
279+ for (int m=0; m<TxtrWidth[n]; m++)
369280 {
370-
371- ::draw_text(FontSurface, &Which, 1, HPos, VPos, White, Info, Style);
372- HPos += widths_p[(unsigned char) (Which++)];
281+ *(DstPxl++) = 0xff; // Base color: white (will be modified with glColorxxx())
282+ *(DstPxl++) = *SrcPxl;
283+ SrcPxl += 4;
373284 }
374285 }
375-#endif
376-
377- // Non-MacOS-specific: allocate the texture buffer
378- // Its format is LA 88, where L is the luminosity and A is the alpha channel
379- // The font value will go into A.
380- OGL_Texture = new uint8[2*GetTxtrSize()];
381286
382-#if defined(mac)
383- // Now copy from the GWorld into the OpenGL texture
384- uint8 *PixBase = (byte *)GetPixBaseAddr(Pxls);
385- int Stride = int((**Pxls).rowBytes & 0x7fff);
386-
387- for (int k=0; k<TxtrHeight; k++)
388- {
389- uint8 *SrcPxl = PixBase + k*Stride + 1; // Use red channel
390- uint8 *DstPxl = OGL_Texture + 2*k*TxtrWidth;
391- for (int m=0; m<TxtrWidth; m++)
392- {
393- *(DstPxl++) = 0xff; // Base color: white (will be modified with glColorxxx())
394- *(DstPxl++) = *SrcPxl;
395- SrcPxl += 4;
396- }
397- }
398-
399- UnlockPixels(Pxls);
400- SetGWorld(OrigPort,OrigDevice);
401- DisposeGWorld(FTGW);
402-
403-#elif defined(SDL)
404- // Copy the SDL surface into the OpenGL texture
405- uint8 *PixBase = (uint8 *)FontSurface->pixels;
406- int Stride = FontSurface->pitch;
407-
408- for (int k=0; k<TxtrHeight; k++)
409- {
410- uint8 *SrcPxl = PixBase + k*Stride + 1; // Use one of the middle channels (red or green or blue)
411- uint8 *DstPxl = OGL_Texture + 2*k*TxtrWidth;
412- for (int m=0; m<TxtrWidth; m++)
413- {
414- *(DstPxl++) = 0xff; // Base color: white (will be modified with glColorxxx())
415- *(DstPxl++) = *SrcPxl;
416- SrcPxl += 4;
417- }
418- }
419-
420287 // Clean up
421- SDL_FreeSurface(FontSurface);
422-#endif
423-
288+ SDL_FreeSurface(s);
289+
424290 // OpenGL stuff starts here
425- // Load texture
426- glGenTextures(1,&TxtrID);
427- glBindTexture(GL_TEXTURE_2D,TxtrID);
428- OGL_Register(this);
429-
430- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
431- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
432- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
433- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
434- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
435- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, TxtrWidth, TxtrHeight,
436- 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, OGL_Texture);
437-
438- // Allocate and create display lists of rendering commands
439- DispList = glGenLists(256);
440- GLfloat TWidNorm = GLfloat(1)/TxtrWidth;
441- GLfloat THtNorm = GLfloat(1)/TxtrHeight;
442- for (int k=0; k<=LastLine; k++)
443- {
444- unsigned char Which = CharStarts[k];
445- GLfloat Top = k*(THtNorm*GlyphHeight);
446- GLfloat Bottom = (k+1)*(THtNorm*GlyphHeight);
447- int Pos = 0;
448- for (int m=0; m<CharCounts[k]; m++)
449- {
450- short Width = widths_p[Which];
451- int NewPos = Pos + Width;
452- GLfloat Left = TWidNorm*Pos;
453- GLfloat Right = TWidNorm*NewPos;
291+ // Load texture
292+ glBindTexture(GL_TEXTURE_2D,TxtrID[n]);
293+
294+
295+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
296+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
297+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
298+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
299+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
300+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
301+ TxtrWidth[n], TxtrHeight[n],
302+ 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, OGL_Texture[n]);
303+
304+ // Allocate and create display lists of rendering commands
305+
306+ GLfloat TWidNorm = GLfloat(1)/TxtrWidth[n];
307+ GLfloat THtNorm = GLfloat(1)/TxtrHeight[n];
308+ GLfloat Bottom = (THtNorm*GlyphHeight);
309+ GLfloat Right = TWidNorm*Widths[n];
310+ glNewList(DispList+n, GL_COMPILE);
454311
455- glNewList(DispList + Which, GL_COMPILE);
312+ // Move to the current glyph's (padded) position
313+ glTranslatef(-Pad,0,0);
456314
457- // Move to the current glyph's (padded) position
458- glTranslatef(-Pad,0,0);
459-
460- // Draw the glyph rectangle
461- // Due to a bug in MacOS X Classic OpenGL, glVertex2s() was changed to glVertex2f()
462- glBegin(GL_POLYGON);
463-
464- glTexCoord2f(Left,Top);
465- glVertex2d(0,-ascent_p);
466-
467- glTexCoord2f(Right,Top);
468- glVertex2d(Width,-ascent_p);
469-
470- glTexCoord2f(Right,Bottom);
471- glVertex2d(Width,descent_p);
472-
473- glTexCoord2f(Left,Bottom);
474- glVertex2d(0,descent_p);
475-
476- glEnd();
477-
478- // Move to the next glyph's position
479- glTranslated(Width-Pad,0,0);
480-
481- glEndList();
482-
483- // For next one
484- Pos = NewPos;
485- Which++;
486- }
487- }
488-#else
489- // Don't delete these if there is no valid texture;
315+ // Draw the glyph rectangle
316+ // Due to a bug in MacOS X Classic OpenGL, glVertex2s() was changed to glVertex2f()
317+ glBegin(GL_POLYGON);
318+ glTexCoord2f(0,0); glVertex2d(0,-ascent_p);
319+ glTexCoord2f(Right,0); glVertex2d(Widths[n],-ascent_p);
320+ glTexCoord2f(Right,Bottom); glVertex2d(Widths[n],descent_p);
321+ glTexCoord2f(0,Bottom); glVertex2d(0,descent_p);
322+ glEnd();
323+
324+ // Move to the next glyph's position
325+ glTranslated(Widths[n]-Pad,0,0);
326+
327+ glEndList();
328+
329+}
330+// Reset the OpenGL fonts; its arg indicates whether this is for starting an OpenGL session
331+// (this is to avoid texture and display-list memory leaks and other such things)
332+void FontSpecifier::OGL_Reset(bool IsStarting)
333+{
334+ // Don't delete these if there is no valid texture;
490335 // that indicates that there are no valid texture and display-list ID's.
491- if (!IsStarting)
336+ if (!IsStarting && OGL_Texture[1] )
492337 {
493- glDeleteTextures(1,&TxtrID);
338+ glDeleteTextures(256,TxtrID);
339+ glDeleteLists(DispList,256);
340+ OGL_Deregister(this);
341+ for(int n = 0; n < 256; ++n ) {
342+ // Invalidates whatever texture had been present
343+ if (OGL_Texture[n])
344+ {
345+ delete [] OGL_Texture[n];
346+ OGL_Texture[n] = NULL;
347+ }
348+ }
494349 }
495- glGenTextures(1,&TxtrID);
496-#endif
350+ textMap.clear();
351+
352+ if (!IsStarting)
353+ return;
354+ glGenTextures(256,TxtrID);
355+ DispList = glGenLists(256);
356+ OGL_Register(this);
357+ // Put some padding around each glyph so as to avoid clipping i
358+ for(int n = 1; n < 128; ++n ) {
359+ char str[] = { n, 0 };
360+ render_text_(n, str);
361+ }
497362 }
498363
499-
364+#include "converter.h"
500365 // Renders a C-style string in OpenGL.
501366 // assumes screen coordinates and that the left baseline point is at (0,0).
502367 // Alters the modelview matrix so that the next characters will be drawn at the proper place.
@@ -503,108 +368,62 @@
503368 // One can surround it with glPushMatrix() and glPopMatrix() to remember the original.
504369 void FontSpecifier::OGL_Render(const char *Text)
505370 {
506-#if 0
371+ const char* tp = Text;
372+
507373 // Bug out if no texture to render
508- if (!OGL_Texture)
374+ if (!OGL_Texture[33])
509375 {
510- OGL_Reset(true);
511- if (!OGL_Texture) return;
376+ OGL_Reset(true);
377+ if (!OGL_Texture[33]) return;
512378 }
513-
514379 glPushAttrib(GL_ENABLE_BIT);
515-
380+
516381 glEnable(GL_TEXTURE_2D);
517382 glDisable(GL_CULL_FACE);
518383 glEnable(GL_BLEND);
519384 glDisable(GL_ALPHA_TEST);
520385 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
386+ while(*tp) {
387+ if( (unsigned char)*tp < 128 ) {
388+ glBindTexture(GL_TEXTURE_2D,TxtrID[*tp]);
389+ glCallList(DispList+*tp);
390+ tp++;
391+ } else {
392+ std::string buffer("");
393+ unsigned char tc, tc2;
394+ do {
395+ buffer += *tp;
396+ tc = *tp++;
397+ tc2 = *tp;
398+ char tcc = *tp;
399+ if( isJChar(tc) && is2ndJChar(tc2) ) {
400+ buffer += tcc;
401+ tp++;
402+ }
403+ } while( *tp && tc > 127 ) ;
521404
522- glBindTexture(GL_TEXTURE_2D,TxtrID);
523-
524- size_t Len = MIN(strlen(Text),255);
525- for (size_t k=0; k<Len; k++)
526- {
527- unsigned char c = Text[k];
528- glCallList(DispList+c);
405+ if( int re = textMap[buffer] ) {
406+ // Already rendered
407+ glBindTexture(GL_TEXTURE_2D,TxtrID[re]);
408+ glCallList(DispList+re);
409+ } else {
410+ if( textMap.size() == 127 ) {
411+ // Buffer is full; clear it
412+ textMap.clear();
413+ glDeleteLists(DispList+128,128);
414+ for(int n = 0; n < 128; ++n ) {
415+ delete [] OGL_Texture[128+n];
416+ OGL_Texture[128+n] = NULL;
417+ }
418+ }
419+ int pm = 128 + textMap.size();
420+ textMap[buffer] = pm;
421+ render_text_(pm, buffer.c_str());
422+ glCallList(DispList+pm);
423+ }
424+ }
529425 }
530-
531426 glPopAttrib();
532-#else
533- SDL_Surface *FontSurface;
534- const int Pad = 0;
535- int ascent_p = Ascent + Pad, descent_p = Descent + Pad;
536- int GlyphHeight = ascent_p + descent_p;
537-
538- size_t Len = MIN(strlen(Text),255);
539- // Put some padding around each glyph so as to avoid clipping it
540-
541- TxtrWidth = NextPowerOfTwo(TextWidth(Text));
542- TxtrHeight = NextPowerOfTwo(GlyphHeight);
543-
544- // Render the font glyphs into the SDL surface
545- FontSurface = SDL_CreateRGBSurface(0, TxtrWidth, TxtrHeight, 32, 0xff0000, 0x00ff00, 0x0000ff, 0xff000000);
546- if (FontSurface == NULL)
547- return;
548- // Set background to black
549- Uint32 White = SDL_MapRGB(FontSurface->format, 0xFF, 0xFF, 0xFF);
550- ::draw_text(FontSurface, Text, strlen(Text), 0, ascent_p, White, Info, Style);
551-
552- glPushAttrib(GL_ALL_ATTRIB_BITS);
553-
554- glEnable(GL_TEXTURE_2D);
555- glDisable(GL_CULL_FACE);
556- glEnable(GL_BLEND);
557- glDisable(GL_ALPHA_TEST);
558-
559- // OpenGL stuff starts here
560- // Load texture
561-
562- glBindTexture(GL_TEXTURE_2D,TxtrID);
563-
564- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
565- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
566- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
567-
568- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, TxtrWidth, TxtrHeight,
569- 0, GL_BGRA, GL_UNSIGNED_BYTE, (uint8 *)FontSurface->pixels);
570-
571- // Allocate and create display lists of rendering commands
572- GLfloat TWidNorm = GLfloat(1)/TxtrWidth;
573- GLfloat THtNorm = GLfloat(1)/TxtrHeight;
574- GLfloat Top = 0;
575- GLfloat Bottom = (THtNorm*GlyphHeight);
576- int Pos = 0;
577- short Width = TxtrWidth;
578- int NewPos = Width;
579- GLfloat Left = 0;
580- GLfloat Right = TWidNorm*NewPos;
581-
582- // Move to the current glyph's (padded) position
583- glTranslatef(-Pad,0,0);
584-
585- // Draw the glyph rectangle
586- // Due to a bug in MacOS X Classic OpenGL, glVertex2s() was changed to glVertex2f()
587- glBegin(GL_POLYGON);
588-
589- glTexCoord2f(Left,Top);
590- glVertex2d(0,-ascent_p);
591-
592- glTexCoord2f(Right,Top);
593- glVertex2d(Width,-ascent_p);
594-
595- glTexCoord2f(Right,Bottom);
596- glVertex2d(Width,descent_p);
597-
598- glTexCoord2f(Left,Bottom);
599- glVertex2d(0,descent_p);
600-
601- glEnd();
602-
603- // Move to the next glyph's position
604- glTranslated(Width-Pad,0,0);
605-
606- glPopAttrib();
607-#endif
608427 }
609428
610429
@@ -616,56 +435,8 @@
616435 char text_to_draw[256];
617436 strncpy(text_to_draw, text, 256);
618437 text_to_draw[255] = 0;
619-#if 0
620- // Check for wrapping, and if it occurs, be recursive
621- if (flags & _wrap_text) {
622- int last_non_printing_character = 0, text_width = 0;
623- unsigned count = 0;
624- while (count < strlen(text_to_draw) && text_width < RECTANGLE_WIDTH(&r)) {
625-
626- text_width += CharWidth(text_to_draw[count]);
627- if (text_to_draw[count] == ' ')
628- last_non_printing_character = count;
629- count++;
630- }
631-
632- if( count != strlen(text_to_draw)) {
633- char remaining_text_to_draw[256];
634-
635- // If we ever have to wrap text, we can't also center vertically. Sorry.
636- flags &= ~_center_vertical;
637- flags |= _top_justified;
638-
639- // Pass the rest of it back in, recursively, on the next line
640- memcpy(remaining_text_to_draw, text_to_draw + last_non_printing_character + 1, strlen(text_to_draw + last_non_printing_character + 1) + 1);
641-
642- screen_rectangle new_destination = r;
643- new_destination.top += LineSpacing;
644- OGL_DrawText(remaining_text_to_draw, new_destination, flags);
645-
646- // Now truncate our text to draw
647- text_to_draw[last_non_printing_character] = 0;
648- }
649- }
650438
651- // Truncate text if necessary
652439 int t_width = TextWidth(text_to_draw);
653- if (t_width > RECTANGLE_WIDTH(&r)) {
654- int width = 0;
655- int num = 0;
656- char c, *p = text_to_draw;
657- while ((c = *p++) != 0) {
658- width += CharWidth(c);
659- if (width > RECTANGLE_WIDTH(&r))
660- break;
661- num++;
662- }
663- text_to_draw[num] = 0;
664- t_width = TextWidth(text_to_draw);
665- }
666-#else
667- int t_width = TextWidth(text_to_draw);
668-#endif
669440
670441 // Horizontal positioning
671442 int x, y;
@@ -703,9 +474,9 @@
703474
704475 void FontSpecifier::OGL_ResetFonts(bool IsStarting)
705476 {
706- if (!m_font_registry)
707- return;
708-
477+ if (!m_font_registry)
478+ return;
479+
709480 set<FontSpecifier*>::iterator it;
710481 if (IsStarting)
711482 {
--- marathon/trunk/Source_Files/RenderOther/OGL_Blitter.cpp (revision 507)
+++ marathon/trunk/Source_Files/RenderOther/OGL_Blitter.cpp (revision 508)
@@ -188,10 +188,20 @@
188188 // zoom to center 640x480, if not in level
189189 if (!in_game && get_screen_mode()->fill_the_screen)
190190 {
191- float scale = std::min(w/(float)640, h/(float)480);
192- glScalef(scale, scale, 1.0);
193- int margin = (480 - h)/2;
194- glTranslatef(margin * w/h, margin, 0.0);
191+ if (w/(float)h >= 640/480.0)
192+ {
193+ float scale = h/480.0;
194+ glScalef(scale, scale, 1.0);
195+ float margin = (480 - h)/2.0;
196+ glTranslatef(margin * w/(float)h, margin, 0.0);
197+ }
198+ else
199+ {
200+ float scale = w/640.0;
201+ glScalef(scale, scale, 1.0);
202+ float margin = (640 - w)/2.0;
203+ glTranslatef(margin, margin * h/(float)w, 0.0);
204+ }
195205 }
196206 glMatrixMode(GL_MODELVIEW);
197207 }
@@ -203,12 +213,24 @@
203213 int w = ScreenWidth();
204214 int h = ScreenHeight();
205215
206- float scale = std::min(w/(float)640, h/(float)480);
207- x /= scale;
208- y /= scale;
209- int margin = (480 - h)/2;
210- x -= margin * w/h;
211- y -= margin;
216+ if (w/(float)h >= 640/480.0)
217+ {
218+ float scale = h/480.0;
219+ x /= scale;
220+ y /= scale;
221+ float margin = (480 - h)/2.0;
222+ x -= margin * w/(float)h;
223+ y -= margin;
224+ }
225+ else
226+ {
227+ float scale = w/640.0;
228+ x /= scale;
229+ y /= scale;
230+ float margin = (640 - w)/2.0;
231+ x -= margin;
232+ y -= margin * h/(float)w;
233+ }
212234 }
213235 }
214236
--- marathon/trunk/Source_Files/RenderOther/sdl_fonts.cpp (revision 507)
+++ marathon/trunk/Source_Files/RenderOther/sdl_fonts.cpp (revision 508)
@@ -82,7 +82,10 @@
8282
8383 void initialize_fonts(void)
8484 {
85- logContext("initializing fonts");
85+ logContext("initializing fonts");
86+ // Font resource file does not contains Japanese font.
87+ // Then, Japanese text render as SDL_ttf and comment out to loading Font file code.
88+/*
8689 // Open font resource files
8790 bool found = false;
8891 vector<DirectorySpecifier>::const_iterator i = data_search_path.begin(), end = data_search_path.end();
@@ -100,24 +103,27 @@
100103 }
101104 i++;
102105 }
106+
103107 if (!found) {
108+*/
104109 #ifdef HAVE_SDL_TTF
105110 // use our own built-in font
106111 fix_missing_overhead_map_fonts();
107112 fix_missing_interface_fonts();
108113 #else
109- logFatal("Can't open font resource file");
114+ //logFatal("Can't open font resource file");
115+ logFatal("AlephOne JP requires SDL_ttf!");
110116 /*
111- vector<DirectorySpecifier>::const_iterator i = data_search_path.begin(), end = data_search_path.end();
112- while (i != end) {
113- FileSpecifier fonts = *i + "Fonts";
114- fdprintf(fonts.GetPath());
115- i++;
116- }
117-*/
117+ vector<DirectorySpecifier>::const_iterator i = data_search_path.begin(), end = data_search_path.end();
118+ while (i != end) {
119+ FileSpecifier fonts = *i + "Fonts";
120+ fdprintf(fonts.GetPath());
121+ i++;
122+ }
123+*/
118124 exit(1);
119125 #endif
120- }
126+// }
121127 }
122128
123129
@@ -124,7 +130,7 @@
124130 /*
125131 * Load font from resources and allocate sdl_font_info
126132 */
127-
133+/*
128134 sdl_font_info *load_sdl_font(const TextSpec &spec)
129135 {
130136 sdl_font_info *info = NULL;
@@ -230,7 +236,7 @@
230236 SDL_RWclose(p);
231237 return info;
232238 }
233-
239+*/
234240 #ifdef HAVE_SDL_TTF
235241 static TTF_Font *load_ttf_font(const std::string& path, uint16 style, int16 size)
236242 {
@@ -246,31 +252,16 @@
246252 }
247253
248254 TTF_Font *font = 0;
249- if (path == "mono" || path == "")
250- {
251- // Japanese Font cannot render as embeded font.
252- // then, if Fonts.ttf exsists, read external font forcely.
253- FILE* fp = fopen( FONT_PATH, "r" );
254- if( !fp ){
255-// fprintf(stderr, "TTF Font %s is not found. Load internal font.\n", FONT_PATH);
256- font = TTF_OpenFontRW(SDL_RWFromConstMem(aleph_sans_mono_bold, sizeof(aleph_sans_mono_bold)), 0, size);
257- }else{
258- font = TTF_OpenFont(FONT_PATH, size);
259- fclose( fp );
260- }
261- }
262- else
263- {
264- short SavedType, SavedError = get_game_error(&SavedType);
265255
266- FileSpecifier fileSpec(path);
267- OpenedFile file;
268- if (fileSpec.Open(file))
269- {
270- font = TTF_OpenFontRW(file.TakeRWops(), 1, size);
271- }
272-
273- set_game_error(SavedType, SavedError);
256+ // Japanese Font cannot render as embeded font.
257+ // then, if Fonts.ttf exsists, read external font forcely.
258+ FILE* fp = fopen( FONT_PATH, "r" );
259+ if( !fp ){
260+ fprintf(stderr, "TTF Font %s is not found. Load internal font. Japanese strings will be garbled.\n", FONT_PATH);
261+ font = TTF_OpenFontRW(SDL_RWFromConstMem(aleph_sans_mono_bold, sizeof(aleph_sans_mono_bold)), 0, size);
262+ }else{
263+ font = TTF_OpenFont(FONT_PATH, size);
264+ fclose( fp );
274265 }
275266
276267 if (font)
@@ -316,10 +307,7 @@
316307 #endif
317308
318309 font_info *load_font(const TextSpec &spec) {
319-// return static_cast<font_info*>(load_font(spec));
320-
321310 #ifdef HAVE_SDL_TTF
322-// if (spec.normal != "")
323311 {
324312 std::string file;
325313 file = locate_font(spec.normal);
@@ -403,28 +391,13 @@
403391 }
404392 }
405393 }
406-
407-
408394 return info;
409395 }
410- //else if (spec.font != -1)
411- //{
412- // return static_cast<font_info *>(load_sdl_font(spec));
413- //}
414- //else
415- return 0;
396+ return 0;
416397 }
417-// else
418398 #endif
419- // if (spec.font != -1)
420-// {
421-// return static_cast<font_info *>(load_sdl_font(spec));
422-// }
423-// else
424-// return 0;
425399 }
426400
427-
428401 /*
429402 * Unload font, free sdl_font_info
430403 */
--- marathon/trunk/Source_Files/Misc/sdl_dialogs.cpp (revision 507)
+++ marathon/trunk/Source_Files/Misc/sdl_dialogs.cpp (revision 508)
@@ -1080,7 +1080,7 @@
10801080 dialog_theme[HYPERLINK_WIDGET].states[PRESSED_STATE].colors[FOREGROUND_COLOR] = make_color(0xff, 0xff, 0xff);
10811081
10821082 dialog_theme[CHECKBOX].font_spec = dialog_theme[DEFAULT_WIDGET].font_spec;
1083- dialog_theme[CHECKBOX].font_spec.size = 22;
1083+ dialog_theme[CHECKBOX].font_spec.size = 16;/* 22 */
10841084 dialog_theme[CHECKBOX].font_set = true;
10851085 dialog_theme[CHECKBOX].spaces[BUTTON_T_SPACE] = 13;
10861086 dialog_theme[CHECKBOX].spaces[BUTTON_HEIGHT] = 15;
--- marathon/trunk/Source_Files/Misc/preferences.cpp (revision 507)
+++ marathon/trunk/Source_Files/Misc/preferences.cpp (revision 508)
@@ -1102,7 +1102,7 @@
11021102 table->dual_add(quality_w, d);
11031103
11041104 stereo_w = new w_stereo_toggle(sound_preferences->flags & _stereo_flag);
1105- table->dual_add(quality_w->label("ステレオ"), d);
1105+ table->dual_add(stereo_w->label("ステレオ"), d);
11061106 table->dual_add(stereo_w, d);
11071107
11081108 dynamic_w = new w_dynamic_toggle(TEST_FLAG(sound_preferences->flags, _dynamic_tracking_flag));
@@ -1286,6 +1286,7 @@
12861286
12871287 mouse_w->add_dependent_widget(mouse_acceleration_w);
12881288
1289+
12891290 w_toggle *invert_mouse_w = new w_toggle(TEST_FLAG(input_preferences->modifiers, _inputmod_invert_mouse));
12901291 mouse->dual_add(invert_mouse_w->label("マウスを反転"), d);
12911292 mouse->dual_add(invert_mouse_w, d);
@@ -1318,7 +1319,7 @@
13181319 (int) ((theSensitivityLog - kMinSensitivityLog) * (1000.0f / kSensitivityLogRange));
13191320
13201321 w_slider* sens_horizontal_w = new w_slider(1000, theHorizontalSliderPosition);
1321- mouse->dual_add(sens_vertical_w->label("マウスの垂平感度"), d);
1322+ mouse->dual_add(sens_horizontal_w->label("マウスの垂平感度"), d);
13221323 mouse->dual_add(sens_horizontal_w, d);
13231324
13241325 mouse_w->add_dependent_widget(sens_horizontal_w);
@@ -1393,21 +1394,17 @@
13931394 w_toggle *always_run_w = new w_toggle(input_preferences->modifiers & _inputmod_interchange_run_walk);
13941395 general_table->dual_add(always_run_w->label("常時走行"), d);
13951396 general_table->dual_add(always_run_w, d);
1396-
13971397 w_toggle *always_swim_w = new w_toggle(TEST_FLAG(input_preferences->modifiers, _inputmod_interchange_swim_sink));
13981398 general_table->dual_add(always_swim_w->label("常時泳ぐ"), d);
13991399 general_table->dual_add(always_swim_w, d);
1400-
14011400 general_table->add_row(new w_spacer(), true);
14021401
14031402 w_toggle *weapon_w = new w_toggle(!(input_preferences->modifiers & _inputmod_dont_switch_to_new_weapon));
14041403 general_table->dual_add(weapon_w->label("武器の自動切換え"), d);
14051404 general_table->dual_add(weapon_w, d);
1406-
14071405 w_toggle* auto_recenter_w = new w_toggle(!(input_preferences->modifiers & _inputmod_dont_auto_recenter));
14081406 general_table->dual_add(auto_recenter_w->label("視点の自動リセンター"), d);
14091407 general_table->dual_add(auto_recenter_w, d);
1410-
14111408 general->add(general_table, true);
14121409
14131410 general->add(new w_spacer(), true);
@@ -1414,7 +1411,6 @@
14141411 general->dual_add(new w_static_text("注意:武器の自動切換えと、視点の自動リセンターは、ネットワークプレイで"), d);
14151412 general->dual_add(new w_static_text("自動的にオンになります。シングルプレイヤーモードでも、映画を録画する際"), d);
14161413 general->dual_add(new w_static_text("どちらかをオフにしても、自動的に無効化されます。"), d);
1417-
14181414 tabs->add(general, true);
14191415 tabs->add(mouse, true);
14201416 tabs->add(joystick, true);
@@ -1441,7 +1437,7 @@
14411437 if (d.run() == 0) { // Accepted
14421438 bool changed = false;
14431439
1444- int16 device = static_cast<int16>(mouse_w->get_selection());
1440+ int16 device = static_cast<int16>(mouse_w->get_selection());
14451441 if (device != input_preferences->input_device) {
14461442 input_preferences->input_device = device;
14471443 changed = true;
@@ -1512,7 +1508,6 @@
15121508 changed = true;
15131509 }
15141510 }
1515-
15161511 if (changed)
15171512 write_preferences();
15181513 }
@@ -3976,155 +3971,155 @@
39763971 XML_EnvironmentPrefsParser(): XML_ElementParser("environment") {}
39773972 };
39783973
3979-bool XML_EnvironmentPrefsParser::HandleAttribute(const char *Tag, const char *Value)
3980-{
3981- if (StringsEqual(Tag,"map_file"))
3982- {
3983- expand_symbolic_paths(environment_preferences->map_file, Value, 255);
3984- return true;
3985- }
3986- else if (StringsEqual(Tag,"physics_file"))
3987- {
3988- expand_symbolic_paths(environment_preferences->physics_file, Value, 255);
3989- return true;
3990- }
3991- else if (StringsEqual(Tag,"shapes_file"))
3992- {
3993- expand_symbolic_paths(environment_preferences->shapes_file, Value, 255);
3994- return true;
3995- }
3996- else if (StringsEqual(Tag,"sounds_file"))
3997- {
3998- expand_symbolic_paths(environment_preferences->sounds_file, Value, 255);
3999- return true;
4000- }
4001- else if (StringsEqual(Tag,"theme_dir"))
4002- {
4003- expand_symbolic_paths(environment_preferences->theme_dir, Value, 255);
4004- return true;
4005- }
4006- else if (StringsEqual(Tag,"map_checksum"))
4007- {
4008- return ReadUInt32Value(Value,environment_preferences->map_checksum);
4009- }
4010- else if (StringsEqual(Tag,"physics_checksum"))
4011- {
4012- return ReadUInt32Value(Value,environment_preferences->physics_checksum);
4013- }
4014- else if (StringsEqual(Tag,"shapes_mod_date"))
4015- {
4016- uint32 ModDate;
4017- if (ReadUInt32Value(Value,ModDate))
4018- {
4019- environment_preferences->shapes_mod_date = TimeType(ModDate);
4020- return true;
4021- }
4022- else
4023- return false;
4024- }
4025- else if (StringsEqual(Tag,"sounds_mod_date"))
4026- {
4027- uint32 ModDate;
4028- if (ReadUInt32Value(Value,ModDate))
4029- {
4030- environment_preferences->sounds_mod_date = TimeType(ModDate);
4031- return true;
4032- }
4033- else
4034- return false;
4035- }
4036- else if (StringsEqual(Tag,"group_by_directory"))
4037- {
4038- return ReadBooleanValue(Value,environment_preferences->group_by_directory);
4039- }
4040- else if (StringsEqual(Tag,"reduce_singletons"))
4041- {
4042- return ReadBooleanValue(Value,environment_preferences->reduce_singletons);
4043- }
4044- else if (StringsEqual(Tag,"non_bungie_warning"))
4045- {
4046- // obsolete
4047- return true;
4048- }
4049- else if (StringsEqual(Tag,"smooth_text"))
4050- {
4051- return ReadBooleanValue(Value, environment_preferences->smooth_text);
4052- }
4053- else if (StringsEqual(Tag,"solo_lua_file"))
4054- {
4055- expand_symbolic_paths(environment_preferences->solo_lua_file, Value, 255);
4056- return true;
4057- }
4058- else if (StringsEqual(Tag,"use_solo_lua"))
4059- {
4060- return ReadBooleanValue(Value, environment_preferences->use_solo_lua);
4061- }
4062- else if (StringsEqual(Tag,"hud_lua_file"))
4063- {
4064- expand_symbolic_paths(environment_preferences->hud_lua_file, Value, 255);
4065- return true;
4066- }
4067- else if (StringsEqual(Tag,"use_hud_lua"))
4068- {
4069- return ReadBooleanValue(Value, environment_preferences->use_hud_lua);
4070- }
4071- else if (StringsEqual(Tag, "hide_alephone_extensions"))
4072- {
4073- return ReadBooleanValue(Value, environment_preferences->hide_extensions);
4074- }
4075- else if (StringsEqual(Tag, "film_profile"))
4076- {
4077- uint32 profile;
4078- if (ReadUInt32Value(Value, profile))
4079- {
4080- environment_preferences->film_profile = static_cast<FilmProfileType>(profile);
4081- return true;
4082- }
4083- return false;
4084- }
4085- return true;
4086-}
4087-
4088-static XML_EnvironmentPrefsParser EnvironmentPrefsParser;
4089-
4090-
4091-
4092-void SetupPrefsParseTree()
4093-{
4094- // Add the root object here
4095- PrefsRootParser.AddChild(&MarathonPrefsParser);
4096-
4097- // Add all the others
4098-
4099- VoidPrefsParser.AddChild(Color_GetParser());
4100- GraphicsPrefsParser.AddChild(&VoidPrefsParser);
4101- LandscapePrefsParser.AddChild(Color_GetParser());
4102- GraphicsPrefsParser.AddChild(&LandscapePrefsParser);
4103- GraphicsPrefsParser.AddChild(&TexturePrefsParser);
4104- MarathonPrefsParser.AddChild(&GraphicsPrefsParser);
4105-
4106- PlayerPrefsParser.AddChild(&ChaseCamPrefsParser);
4107- CrosshairsPrefsParser.AddChild(Color_GetParser());
4108- PlayerPrefsParser.AddChild(&CrosshairsPrefsParser);
4109- MarathonPrefsParser.AddChild(&PlayerPrefsParser);
4110-
4111- InputPrefsParser.AddChild(&MouseButtonPrefsParser);
4112- InputPrefsParser.AddChild(&AxisMappingPrefsParser);
4113- InputPrefsParser.AddChild(&MacKeyPrefsParser);
4114- InputPrefsParser.AddChild(&SDLKeyPrefsParser);
4115- MarathonPrefsParser.AddChild(&InputPrefsParser);
4116-
4117- MarathonPrefsParser.AddChild(&SoundPrefsParser);
4118-
4119-#if !defined(DISABLE_NETWORKING)
4120- NetworkPrefsParser.AddChild(Color_GetParser());
4121- NetworkPrefsParser.AddChild(StarGameProtocol::GetParser());
4122- NetworkPrefsParser.AddChild(RingGameProtocol::GetParser());
4123-#endif // !defined(DISABLE_NETWORKING)
4124- NetworkPrefsParser.AddChild(&MacFSSpecPrefsParser);
4125- MarathonPrefsParser.AddChild(&NetworkPrefsParser);
4126-
4127- EnvironmentPrefsParser.AddChild(&MacFSSpecPrefsParser);
4128- EnvironmentPrefsParser.AddChild(&DisablePluginsParser);
4129- MarathonPrefsParser.AddChild(&EnvironmentPrefsParser);
4130-}
3974+bool XML_EnvironmentPrefsParser::HandleAttribute(const char *Tag, const char *Value)
3975+{
3976+ if (StringsEqual(Tag,"map_file"))
3977+ {
3978+ expand_symbolic_paths(environment_preferences->map_file, Value, 255);
3979+ return true;
3980+ }
3981+ else if (StringsEqual(Tag,"physics_file"))
3982+ {
3983+ expand_symbolic_paths(environment_preferences->physics_file, Value, 255);
3984+ return true;
3985+ }
3986+ else if (StringsEqual(Tag,"shapes_file"))
3987+ {
3988+ expand_symbolic_paths(environment_preferences->shapes_file, Value, 255);
3989+ return true;
3990+ }
3991+ else if (StringsEqual(Tag,"sounds_file"))
3992+ {
3993+ expand_symbolic_paths(environment_preferences->sounds_file, Value, 255);
3994+ return true;
3995+ }
3996+ else if (StringsEqual(Tag,"theme_dir"))
3997+ {
3998+ expand_symbolic_paths(environment_preferences->theme_dir, Value, 255);
3999+ return true;
4000+ }
4001+ else if (StringsEqual(Tag,"map_checksum"))
4002+ {
4003+ return ReadUInt32Value(Value,environment_preferences->map_checksum);
4004+ }
4005+ else if (StringsEqual(Tag,"physics_checksum"))
4006+ {
4007+ return ReadUInt32Value(Value,environment_preferences->physics_checksum);
4008+ }
4009+ else if (StringsEqual(Tag,"shapes_mod_date"))
4010+ {
4011+ uint32 ModDate;
4012+ if (ReadUInt32Value(Value,ModDate))
4013+ {
4014+ environment_preferences->shapes_mod_date = TimeType(ModDate);
4015+ return true;
4016+ }
4017+ else
4018+ return false;
4019+ }
4020+ else if (StringsEqual(Tag,"sounds_mod_date"))
4021+ {
4022+ uint32 ModDate;
4023+ if (ReadUInt32Value(Value,ModDate))
4024+ {
4025+ environment_preferences->sounds_mod_date = TimeType(ModDate);
4026+ return true;
4027+ }
4028+ else
4029+ return false;
4030+ }
4031+ else if (StringsEqual(Tag,"group_by_directory"))
4032+ {
4033+ return ReadBooleanValue(Value,environment_preferences->group_by_directory);
4034+ }
4035+ else if (StringsEqual(Tag,"reduce_singletons"))
4036+ {
4037+ return ReadBooleanValue(Value,environment_preferences->reduce_singletons);
4038+ }
4039+ else if (StringsEqual(Tag,"non_bungie_warning"))
4040+ {
4041+ // obsolete
4042+ return true;
4043+ }
4044+ else if (StringsEqual(Tag,"smooth_text"))
4045+ {
4046+ return ReadBooleanValue(Value, environment_preferences->smooth_text);
4047+ }
4048+ else if (StringsEqual(Tag,"solo_lua_file"))
4049+ {
4050+ expand_symbolic_paths(environment_preferences->solo_lua_file, Value, 255);
4051+ return true;
4052+ }
4053+ else if (StringsEqual(Tag,"use_solo_lua"))
4054+ {
4055+ return ReadBooleanValue(Value, environment_preferences->use_solo_lua);
4056+ }
4057+ else if (StringsEqual(Tag,"hud_lua_file"))
4058+ {
4059+ expand_symbolic_paths(environment_preferences->hud_lua_file, Value, 255);
4060+ return true;
4061+ }
4062+ else if (StringsEqual(Tag,"use_hud_lua"))
4063+ {
4064+ return ReadBooleanValue(Value, environment_preferences->use_hud_lua);
4065+ }
4066+ else if (StringsEqual(Tag, "hide_alephone_extensions"))
4067+ {
4068+ return ReadBooleanValue(Value, environment_preferences->hide_extensions);
4069+ }
4070+ else if (StringsEqual(Tag, "film_profile"))
4071+ {
4072+ uint32 profile;
4073+ if (ReadUInt32Value(Value, profile))
4074+ {
4075+ environment_preferences->film_profile = static_cast<FilmProfileType>(profile);
4076+ return true;
4077+ }
4078+ return false;
4079+ }
4080+ return true;
4081+}
4082+
4083+static XML_EnvironmentPrefsParser EnvironmentPrefsParser;
4084+
4085+
4086+
4087+void SetupPrefsParseTree()
4088+{
4089+ // Add the root object here
4090+ PrefsRootParser.AddChild(&MarathonPrefsParser);
4091+
4092+ // Add all the others
4093+
4094+ VoidPrefsParser.AddChild(Color_GetParser());
4095+ GraphicsPrefsParser.AddChild(&VoidPrefsParser);
4096+ LandscapePrefsParser.AddChild(Color_GetParser());
4097+ GraphicsPrefsParser.AddChild(&LandscapePrefsParser);
4098+ GraphicsPrefsParser.AddChild(&TexturePrefsParser);
4099+ MarathonPrefsParser.AddChild(&GraphicsPrefsParser);
4100+
4101+ PlayerPrefsParser.AddChild(&ChaseCamPrefsParser);
4102+ CrosshairsPrefsParser.AddChild(Color_GetParser());
4103+ PlayerPrefsParser.AddChild(&CrosshairsPrefsParser);
4104+ MarathonPrefsParser.AddChild(&PlayerPrefsParser);
4105+
4106+ InputPrefsParser.AddChild(&MouseButtonPrefsParser);
4107+ InputPrefsParser.AddChild(&AxisMappingPrefsParser);
4108+ InputPrefsParser.AddChild(&MacKeyPrefsParser);
4109+ InputPrefsParser.AddChild(&SDLKeyPrefsParser);
4110+ MarathonPrefsParser.AddChild(&InputPrefsParser);
4111+
4112+ MarathonPrefsParser.AddChild(&SoundPrefsParser);
4113+
4114+#if !defined(DISABLE_NETWORKING)
4115+ NetworkPrefsParser.AddChild(Color_GetParser());
4116+ NetworkPrefsParser.AddChild(StarGameProtocol::GetParser());
4117+ NetworkPrefsParser.AddChild(RingGameProtocol::GetParser());
4118+#endif // !defined(DISABLE_NETWORKING)
4119+ NetworkPrefsParser.AddChild(&MacFSSpecPrefsParser);
4120+ MarathonPrefsParser.AddChild(&NetworkPrefsParser);
4121+
4122+ EnvironmentPrefsParser.AddChild(&MacFSSpecPrefsParser);
4123+ EnvironmentPrefsParser.AddChild(&DisablePluginsParser);
4124+ MarathonPrefsParser.AddChild(&EnvironmentPrefsParser);
4125+}
--- marathon/trunk/Source_Files/Misc/sdl_widgets.cpp (revision 507)
+++ marathon/trunk/Source_Files/Misc/sdl_widgets.cpp (revision 508)
@@ -697,7 +697,7 @@
697697 // if no valid labels, returns -1 when asked for selection
698698 // draw(), get_selection() check num_labels directly instead of trying to keep selection set at -1
699699
700-static const char* sNoValidOptionsString = "(no valid options)"; // XXX should be moved outside compiled code e.g. to MML
700+static const char* sNoValidOptionsString = "(無効な指定)"; // XXX should be moved outside compiled code e.g. to MML
701701
702702 w_select::w_select(size_t s, const char **l) : widget(LABEL_WIDGET), labels(l), we_own_labels(false), selection(s), selection_changed_callback(NULL), utf8(false)
703703 {
@@ -890,8 +890,7 @@
890890 */
891891
892892 #ifdef HAVE_SDL_TTF
893-//const char *w_toggle::onoff_labels[] = {"\342\230\220", "\342\230\221", NULL };
894-const char *w_toggle::onoff_labels[] = {"笘?, "笘?, NULL };
893+const char *w_toggle::onoff_labels[] = {"\342\230\220", "\342\230\221", NULL };
895894 #else
896895 const char *w_toggle::onoff_labels[] = {"Off", "On", NULL};
897896 #endif
@@ -1032,7 +1031,7 @@
10321031 dialog d;
10331032
10341033 vertical_placer *placer = new vertical_placer;
1035- placer->dual_add(new w_title("CHOOSE A COLOR"), d);
1034+ placer->dual_add(new w_title("色を選択"), d);
10361035 placer->add(new w_spacer(), true);
10371036
10381037 w_color_block *color_block = new w_color_block(&m_color);
@@ -1042,15 +1041,15 @@
10421041 table->col_flags(0, placeable::kAlignRight);
10431042
10441043 w_slider *red_w = new w_slider(16, m_color.red >> 12);
1045- table->dual_add(red_w->label("Red"), d);
1044+ table->dual_add(red_w->label("赤"), d);
10461045 table->dual_add(red_w, d);
10471046
10481047 w_slider *green_w = new w_slider(16, m_color.green >> 12);
1049- table->dual_add(green_w->label("Green"), d);
1048+ table->dual_add(green_w->label("緑"), d);
10501049 table->dual_add(green_w, d);
10511050
10521051 w_slider *blue_w = new w_slider(16, m_color.blue >> 12);
1053- table->dual_add(blue_w->label("Blue"), d);
1052+ table->dual_add(blue_w->label("青"), d);
10541053 table->dual_add(blue_w, d);
10551054
10561055 placer->add(table, true);
@@ -1057,7 +1056,7 @@
10571056 placer->add(new w_spacer(), true);
10581057
10591058 horizontal_placer *button_placer = new horizontal_placer;
1060- button_placer->dual_add(new w_button("CANCEL", dialog_cancel, &d), d);
1059+ button_placer->dual_add(new w_button("キャンセル", dialog_cancel, &d), d);
10611060 button_placer->dual_add(new w_button("OK", dialog_ok, &d), d);
10621061
10631062 placer->add(button_placer, true);
@@ -1293,7 +1292,7 @@
12931292 * Key name widget
12941293 */
12951294
1296-static const char *WAITING_TEXT = "waiting for new key";
1295+static const char *WAITING_TEXT = "キー入力待ち";
12971296
12981297 w_key::w_key(SDLKey key) : widget(LABEL_WIDGET), binding(false)
12991298 {
--- marathon/trunk/Source_Files/Misc/alephversion.h (revision 507)
+++ marathon/trunk/Source_Files/Misc/alephversion.h (revision 508)
@@ -24,9 +24,9 @@
2424
2525
2626 #define A1_DISPLAY_NAME "Aleph One JP"
27-#define A1_DISPLAY_VERSION "1.0"
28-#define A1_DISPLAY_DATE_VERSION "2011-12-02"
29-#define A1_DATE_VERSION "20111202"
27+#define A1_DISPLAY_VERSION "1.0JP2"
28+#define A1_DISPLAY_DATE_VERSION "2011-12-15"
29+#define A1_DATE_VERSION "20111215"
3030
3131 #ifdef WIN32
3232 #define A1_DISPLAY_PLATFORM "Windows"
--- marathon/trunk/Source_Files/CSeries/converter.cpp (revision 507)
+++ marathon/trunk/Source_Files/CSeries/converter.cpp (revision 508)
@@ -53,12 +53,13 @@
5353 // Convert from Shift_JIS to Unidode
5454 // AlephOneJP overrides to process_macroman().
5555 uint16* sjis2utf16(const char* str, size_t len) {
56- static char base[1024]; // in case lastn letter is MAC_LINE_END
57- strncpy(base, str, len);
58- if( base[len-1] == MAC_LINE_END ) {
59- base[len-1] = '\0';
60- --len;
61-}
56+ static char base[1024]; // in case lastn letter is MAC_LINE_END
57+ memset(base, 0, 1024);
58+ strncpy(base, str, len);
59+ if( base[len-1] == MAC_LINE_END ) {
60+ base[len-1] = '\0';
61+ --len;
62+ }
6263 static uint16 text[1024];
6364 memset(text,0,2048);
6465 const char* strp = base;
--- marathon/trunk/PBProjects/AppStore/Marathon Infinity/Marathon Infinity.plist (revision 507)
+++ marathon/trunk/PBProjects/AppStore/Marathon Infinity/Marathon Infinity.plist (revision 508)
@@ -244,6 +244,15 @@
244244 <string>public.app-category.action-games</string>
245245 <key>LSMinimumSystemVersion</key>
246246 <string>10.4.0</string>
247+ <key>LSMinimumSystemVersionByArchitecture</key>
248+ <dict>
249+ <key>i386</key>
250+ <string>10.4.0</string>
251+ <key>ppc</key>
252+ <string>10.4.0</string>
253+ <key>x86_64</key>
254+ <string>10.6.0</string>
255+ </dict>
247256 <key>NSMainNibFile</key>
248257 <string>MainMenu</string>
249258 <key>NSPrincipalClass</key>
--- marathon/trunk/PBProjects/AppStore/Marathon/Marathon.plist (revision 507)
+++ marathon/trunk/PBProjects/AppStore/Marathon/Marathon.plist (revision 508)
@@ -244,6 +244,15 @@
244244 <string>public.app-category.action-games</string>
245245 <key>LSMinimumSystemVersion</key>
246246 <string>10.4.0</string>
247+ <key>LSMinimumSystemVersionByArchitecture</key>
248+ <dict>
249+ <key>i386</key>
250+ <string>10.4.0</string>
251+ <key>ppc</key>
252+ <string>10.4.0</string>
253+ <key>x86_64</key>
254+ <string>10.6.0</string>
255+ </dict>
247256 <key>NSMainNibFile</key>
248257 <string>MainMenu</string>
249258 <key>NSPrincipalClass</key>
--- marathon/trunk/PBProjects/AppStore/Marathon 2/Marathon 2.plist (revision 507)
+++ marathon/trunk/PBProjects/AppStore/Marathon 2/Marathon 2.plist (revision 508)
@@ -244,6 +244,15 @@
244244 <string>public.app-category.action-games</string>
245245 <key>LSMinimumSystemVersion</key>
246246 <string>10.4.0</string>
247+ <key>LSMinimumSystemVersionByArchitecture</key>
248+ <dict>
249+ <key>i386</key>
250+ <string>10.4.0</string>
251+ <key>ppc</key>
252+ <string>10.4.0</string>
253+ <key>x86_64</key>
254+ <string>10.6.0</string>
255+ </dict>
247256 <key>NSMainNibFile</key>
248257 <string>MainMenu</string>
249258 <key>NSPrincipalClass</key>
旧リポジトリブラウザで表示