def_object.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #include "lisp/lisp.hh"
  9. #include "objs/miscobjs.hh"
  10. #include "g1_object.hh"
  11. #include "lisp/li_class.hh"
  12. #include "objs/model_id.hh"
  13. #include "saver.hh"
  14. #include "objs/model_draw.hh"
  15. #include "objs/def_object.hh"
  16. #include "li_objref.hh"
  17. #include "lisp/li_vect.hh"
  18. #include "lisp/li_dialog.hh"
  19. #include "map_man.hh"
  20. #include "map.hh"
  21. static li_symbol *s_model_name=0, *s_mini_object=0,
  22. *s_offset=0, *s_position=0, *s_rotation=0,
  23. *s_object_flags=0, *s_type_flags=0;
  24. static li_symbol *s_ofun[G1_F_TOTAL];
  25. //////////////////// li_def_object setup code ///////////////////////////////////////
  26. // these flag value are assigned ot their symbol names for easy ussage in script files
  27. static w32 g1_oflag_values[]={g1_object_class::THINKING,
  28. g1_object_class::SELECTABLE,
  29. g1_object_class::TARGETABLE,
  30. g1_object_class::GROUND,
  31. g1_object_class::UNDERWATER,
  32. g1_object_class::AERIAL,
  33. g1_object_class::HIT_GROUND,
  34. g1_object_class::HIT_UNDERWATER,
  35. g1_object_class::HIT_AERIAL,
  36. g1_object_class::BLOCKING,
  37. g1_object_class::DANGEROUS,
  38. g1_object_class::CAN_DRIVE_ON
  39. };
  40. static char *g1_oflag_names[]={"thinking",
  41. "selectable",
  42. "targetable",
  43. "ground",
  44. "underwater",
  45. "aerial",
  46. "hit_ground",
  47. "hit_underwater",
  48. "hit_aerial",
  49. "blocking",
  50. "dangerous",
  51. "can_drive_on",
  52. 0};
  53. static char *g1_ofun_names[G1_F_TOTAL]={"think",
  54. "damage",
  55. "notify_damage",
  56. "enter_range",
  57. "draw",
  58. "message",
  59. "deploy_to",
  60. "change_player_num",
  61. "occupy_location",
  62. "unoccupy_location"};
  63. li_object *li_def_object(li_object *o, li_environment *env);
  64. li_object *li_def_buildings(li_object *o, li_environment *env)
  65. {
  66. for (; o; o=li_cdr(o,env))
  67. g1_create_deco_object(li_string::get(li_eval(li_car(o,env), env),env)->value());
  68. return 0;
  69. }
  70. class g1_create_object_init : public i4_init_class
  71. {
  72. public:
  73. void init()
  74. {
  75. int i=0;
  76. for (char **a=g1_oflag_names; *a; a++)
  77. li_set_value(*a, new li_int(g1_oflag_values[i++]));
  78. for (i=0; i<G1_F_TOTAL; i++)
  79. s_ofun[i]=li_get_symbol(g1_ofun_names[i]);
  80. li_set_value("editor_selectable", new li_int(g1_object_definition_class::EDITOR_SELECTABLE));
  81. li_set_value("movable", new li_int(g1_object_definition_class::MOVABLE));
  82. li_add_function("def_object", li_def_object);
  83. li_add_function("def_buildings", li_def_buildings);
  84. }
  85. } g1_create_object_init_instance;
  86. struct g1_object_def_struct
  87. {
  88. char *name;
  89. char *model_name;
  90. i4_array<g1_mini_object_def> *minis;
  91. li_type_number var_class;
  92. w32 flags;
  93. g1_object_def_struct()
  94. {
  95. name=0;
  96. minis=0;
  97. var_class=0;
  98. flags=0;
  99. }
  100. } ;
  101. ///////////////////////////// Dynamic object code ///////////////////////////////
  102. void g1_mini_object_def::assign_to(g1_mini_object *m)
  103. {
  104. m->offset=offset;
  105. m->x=m->lx=position.x;
  106. m->y=m->ly=position.y;
  107. m->h=m->lh=position.z;
  108. m->rotation=m->lrotation=rotation;
  109. m->defmodeltype=defmodeltype;
  110. m->frame=0;
  111. m->animation=0;
  112. }
  113. g1_dynamic_object_type_class::g1_dynamic_object_type_class(li_symbol *sym)
  114. : g1_object_definition_class(sym->name()->value()),
  115. minis(0,1)
  116. {
  117. obj_flags=g1_object_class::CAN_DRIVE_ON;
  118. var_class=0;
  119. flags |= TO_DYNAMIC_OBJECT;
  120. memset(&funs, 0, sizeof(funs));
  121. }
  122. li_object *g1_dynamic_object_class::message(li_symbol *name, li_object *params, li_environment *env)
  123. {
  124. g1_dynamic_object_type_class *t=get_type();
  125. if (t->funs[G1_F_MESSAGE])
  126. {
  127. li_class_context context(vars);
  128. li_g1_ref _me(global_id);
  129. li_list *p=(li_list *)params;
  130. li_push(p, name);
  131. li_push(p, &_me);
  132. return t->funs[G1_F_MESSAGE](p , env);
  133. }
  134. return 0;
  135. }
  136. g1_draw_context_class *g1_draw_context;
  137. // called when the object is on a map cell that is drawn
  138. void g1_dynamic_object_class::draw(g1_draw_context_class *context)
  139. {
  140. g1_dynamic_object_type_class *t=get_type();
  141. if (t->funs[G1_F_DRAW])
  142. {
  143. g1_draw_context=context;
  144. li_class_context context(vars);
  145. li_g1_ref _me(global_id);
  146. t->funs[G1_F_DRAW](li_make_list(&_me,0),0);
  147. }
  148. else
  149. {
  150. g1_model_draw_parameters mp;
  151. mp.model=get_type()->model;
  152. g1_model_draw(this, mp, context);
  153. }
  154. }
  155. // void g1_dynamic_object_class::note_enter_range(g1_object_class *who, g1_fire_range_type range)
  156. // {
  157. // g1_dynamic_object_type_class *t=get_type();
  158. // if (t->funs[G1_F_ENTER_RANGE])
  159. // {
  160. // li_class_context context(vars);
  161. // t->funs[G1_F_ENTER_RANGE](li_make_list(new li_g1_ref(global_id),
  162. // new li_g1_ref(who->global_id),
  163. // new li_int(range), 0), 0);
  164. // }
  165. // }
  166. void g1_dynamic_object_class::damage(g1_object_class *obj, int hp, i4_3d_vector damage_dir)
  167. {
  168. g1_dynamic_object_type_class *t=get_type();
  169. if (t->funs[G1_F_DAMAGE])
  170. {
  171. li_class_context context(vars);
  172. t->funs[G1_F_DAMAGE](li_make_list(new li_g1_ref(global_id),
  173. new li_g1_ref(obj->global_id),
  174. new li_int(hp),
  175. new li_vect(damage_dir), 0),0);
  176. }
  177. else
  178. request_think();
  179. }
  180. void g1_dynamic_object_class::notify_damage(g1_object_class *obj, int hp, w32 notes)
  181. {
  182. g1_dynamic_object_type_class *t=get_type();
  183. if (t->funs[G1_F_NOTIFY_DAMAGE])
  184. {
  185. li_class_context context(vars);
  186. t->funs[G1_F_NOTIFY_DAMAGE](li_make_list(new li_g1_ref(global_id),
  187. new li_g1_ref(obj->global_id),
  188. new li_int(hp),
  189. new li_int(notes), 0),0);
  190. }
  191. else
  192. g1_object_class::notify_damage(obj, hp);
  193. }
  194. void g1_dynamic_object_class::think()
  195. {
  196. g1_dynamic_object_type_class *t=get_type();
  197. if (t->funs[G1_F_THINK])
  198. {
  199. li_class_context context(vars);
  200. t->funs[G1_F_THINK](li_make_list(new li_g1_ref(global_id), 0), 0);
  201. }
  202. }
  203. static li_float_class_member dest_x("dest_x"), dest_y("dest_y");
  204. i4_bool g1_dynamic_object_class::deploy_to(float x, float y)
  205. {
  206. g1_dynamic_object_type_class *t=get_type();
  207. li_class_context context(vars);
  208. if (t->funs[G1_F_DEPLOY_TO])
  209. t->funs[G1_F_DEPLOY_TO](li_make_list(new li_g1_ref(global_id),
  210. new li_float(x),
  211. new li_float(y),0), 0);
  212. else
  213. {
  214. if (vars && vars->member_offset(dest_x)!=-1)
  215. {
  216. dest_x()=x;
  217. dest_y()=y;
  218. }
  219. }
  220. return 0;
  221. }
  222. void g1_dynamic_object_class::change_player_num(int new_player)
  223. {
  224. g1_dynamic_object_type_class *t=get_type();
  225. if (t->funs[G1_F_CHANGE_TEAMS])
  226. {
  227. li_class_context context(vars);
  228. t->funs[G1_F_CHANGE_TEAMS](li_make_list(new li_g1_ref(global_id),
  229. new li_int(new_player), 0), 0);
  230. }
  231. else
  232. g1_object_class::change_player_num(new_player);
  233. }
  234. i4_bool g1_dynamic_object_class::occupy_location()
  235. {
  236. g1_dynamic_object_type_class *t=get_type();
  237. if (t->funs[G1_F_OCCUPY_LOCATION])
  238. {
  239. li_class_context context(vars);
  240. if (t->funs[G1_F_OCCUPY_LOCATION](li_make_list(new li_g1_ref(global_id),0), 0))
  241. return i4_T;
  242. else return i4_F;
  243. }
  244. else
  245. return g1_object_class::occupy_location();
  246. }
  247. void g1_dynamic_object_class::unoccupy_location()
  248. {
  249. g1_dynamic_object_type_class *t=get_type();
  250. if (t->funs[G1_F_UNOCCUPY_LOCATION])
  251. {
  252. li_class_context context(vars);
  253. t->funs[G1_F_UNOCCUPY_LOCATION](li_make_list(new li_g1_ref(global_id), 0), 0);
  254. }
  255. else
  256. g1_object_class::unoccupy_location();
  257. }
  258. g1_dynamic_object_class::g1_dynamic_object_class(g1_object_type type, g1_loader_class *fp)
  259. : g1_object_class(type, fp)
  260. {
  261. g1_dynamic_object_type_class *dtype=get_type();
  262. if (dtype->minis.size())
  263. {
  264. allocate_mini_objects(dtype->minis.size(), "");
  265. for (int i=0; i<dtype->minis.size(); i++)
  266. dtype->minis[i].assign_to(mini_objects+i);
  267. }
  268. if (fp && fp->read_16()==VERSION)
  269. {
  270. int old_minis=fp->read_8(), i;
  271. int old_mini_disk_size=fp->read_32();
  272. if (old_minis==dtype->minis.size())
  273. {
  274. g1_mini_object *m=mini_objects;
  275. for (i=0; i<dtype->minis.size(); i++)
  276. {
  277. fp->read_format("fffffffff",
  278. &m->offset.x, &m->offset.y, &m->offset.z,
  279. &m->x, &m->y, &m->h,
  280. &m->rotation.x, &m->rotation.y, &m->rotation.z);
  281. }
  282. }
  283. else
  284. fp->seek(fp->tell() + old_mini_disk_size);
  285. }
  286. flags = get_type()->obj_flags;
  287. grab_old();
  288. }
  289. void g1_dynamic_object_class::save(g1_saver_class *fp)
  290. {
  291. g1_object_class::save(fp);
  292. fp->write_16(VERSION);
  293. fp->write_8(num_mini_objects);
  294. int han=fp->mark_size();
  295. g1_mini_object *m=mini_objects;
  296. for (int i=0; i<num_mini_objects; i++)
  297. {
  298. fp->write_format("fffffffff",
  299. &m->offset.x, &m->offset.y, &m->offset.z,
  300. &m->x, &m->y, &m->h,
  301. &m->rotation.x, &m->rotation.y, &m->rotation.z);
  302. }
  303. fp->end_mark_size(han);
  304. }
  305. ////////////////// dynamic object type functions ///////////////////////////////
  306. g1_object_class *g1_dynamic_object_type_class::create_object(g1_object_type type,
  307. g1_loader_class *fp)
  308. {
  309. g1_object_class *o=new g1_dynamic_object_class(type, fp);
  310. o->init();
  311. return o;
  312. }
  313. static void read_vect(i4_3d_vector &v, li_object *o, li_environment *env)
  314. {
  315. v.x=li_get_float(li_eval(li_car(o,env), env),env); o=li_cdr(o,env);
  316. v.y=li_get_float(li_eval(li_car(o,env), env),env); o=li_cdr(o,env);
  317. v.z=li_get_float(li_eval(li_car(o,env), env),env);
  318. }
  319. static li_function_type get_function(li_object *o, li_environment *env)
  320. {
  321. li_object *fun=li_get_fun(li_symbol::get(o,env),env);
  322. if (!fun)
  323. li_error(env, "no registered function %O", o);
  324. return li_function::get(fun,env)->value();
  325. }
  326. li_object *li_def_object(li_object *o, li_environment *env)
  327. {
  328. li_symbol *sym=li_symbol::get(li_car(o,env),env);
  329. g1_dynamic_object_type_class *type=new g1_dynamic_object_type_class(sym);
  330. for (li_object *l=li_cdr(o,env); l; l=li_cdr(l,env))
  331. {
  332. li_object *prop=li_car(l,env);
  333. li_symbol *sym=li_symbol::get(li_car(prop,env),env);
  334. prop=li_cdr(prop,env);
  335. if (sym==li_get_symbol("model_name", s_model_name))
  336. {
  337. int id=g1_model_list_man.find_handle(li_string::get(li_car(prop,env),env)->value());
  338. type->model=g1_model_list_man.get_model(id);
  339. }
  340. else if (sym==li_get_symbol("mini_object", s_mini_object))
  341. {
  342. g1_mini_object_def mo;
  343. mo.init();
  344. char *name=0;
  345. for (;prop; prop=li_cdr(prop,env)) // prop = ((offset 0 0 0.1) (center 0 0 0) "gunport_barrel")
  346. {
  347. li_object *sub=li_car(prop,env);
  348. sym=li_symbol::get(li_car(sub,env),env); sub=li_cdr(sub,env);
  349. if (sym==li_get_symbol("offset", s_offset))
  350. read_vect(mo.offset, sub, env);
  351. else if (sym==li_get_symbol("position", s_position))
  352. read_vect(mo.position, sub, env);
  353. else if (sym==li_get_symbol("rotation", s_rotation))
  354. read_vect(mo.rotation, sub, env);
  355. else if (sym==li_get_symbol("model_name", s_model_name))
  356. {
  357. char *n=li_string::get(li_eval(li_car(sub,env), env),env)->value();
  358. mo.defmodeltype=g1_model_list_man.find_handle(n);
  359. }
  360. else li_error(env,"%O should be (offset/position/rotation x y z)",sym);
  361. }
  362. type->minis.add(mo);
  363. }
  364. else if (sym==li_get_symbol("object_flags", s_object_flags))
  365. {
  366. for (;prop; prop=li_cdr(prop,env))
  367. type->obj_flags |= li_int::get(li_eval(li_car(prop,env),env),env)->value();
  368. }
  369. else if (sym==li_get_symbol("type_flags", s_type_flags))
  370. {
  371. for (;prop; prop=li_cdr(prop,env))
  372. type->flags |= li_int::get(li_eval(li_car(prop,env),env),env)->value();
  373. }
  374. else
  375. {
  376. int found=0;
  377. for (int i=0; i<G1_F_TOTAL; i++)
  378. if (sym==s_ofun[i])
  379. {
  380. type->funs[i]=get_function(li_car(prop,env),env);
  381. found=1;
  382. }
  383. if (!found)
  384. li_error(env,"unknown object property %O", sym);
  385. }
  386. }
  387. // if functions were not filled in see if we can find defaults
  388. for (int i=0; i<G1_F_TOTAL; i++)
  389. if (type->funs[i]==0)
  390. {
  391. char buf[200];
  392. sprintf(buf, "%s_%s", type->name(), g1_ofun_names[i]);
  393. li_symbol *sym=li_find_symbol(buf);
  394. if (sym)
  395. {
  396. li_function *fun=li_function::get(sym->fun(), env);
  397. if (fun)
  398. type->funs[i]=li_function::get(fun, env)->value();
  399. }
  400. }
  401. type->flags|=g1_object_definition_class::DELETE_WITH_LEVEL;
  402. return 0;
  403. }