00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023 #include "Audio.h"
00024 #include "Book_gump.h"
00025 #include "Gump.h"
00026 #include "Gump_manager.h"
00027 #include "Scroll_gump.h"
00028 #include "Sign_gump.h"
00029 #include "items.h"
00030 #include "barge.h"
00031 #include "bodies.h"
00032 #include "cheat.h"
00033 #include "chunks.h"
00034 #include "conversation.h"
00035 #include "effects.h"
00036 #include "exult.h"
00037 #include "game.h"
00038 #include "gamewin.h"
00039 #include "gamemap.h"
00040 #include "gameclk.h"
00041 #include "keyring.h"
00042 #include "mouse.h"
00043 #include "rect.h"
00044 #include "schedule.h"
00045 #include "spellbook.h"
00046 #include "ucinternal.h"
00047 #include "ucsched.h"
00048 #include "useval.h"
00049 #include "virstone.h"
00050 #include "monsters.h"
00051 #include "egg.h"
00052 #include "monstinf.h"
00053 #include "actions.h"
00054 #include "ucscriptop.h"
00055 #include "ucfunction.h"
00056 #include "palette.h"
00057 #include "stackframe.h"
00058 #include "party.h"
00059
00060 #ifndef UNDER_CE
00061 using std::cerr;
00062 using std::cout;
00063 using std::endl;
00064 using std::rand;
00065 using std::strchr;
00066 #endif
00067
00068 Barge_object *Get_barge (Game_object *obj);
00069 extern Usecode_value no_ret;
00070
00071 static Game_object *sailor = 0;
00072
00073
00074 #define PARTY_MAX (sizeof(party)/sizeof(party[0]))
00075
00076 #define USECODE_INTRINSIC(NAME) Usecode_value Usecode_internal:: UI_## NAME (int event,int intrinsic,int num_parms,Usecode_value parms[12])
00077
00078 USECODE_INTRINSIC(NOP)
00079 {
00080 return(no_ret);
00081 }
00082
00083 USECODE_INTRINSIC(UNKNOWN)
00084 {
00085
00086 return(no_ret);
00087 }
00088
00089 USECODE_INTRINSIC(get_random)
00090 {
00091 int range = parms[0].get_int_value();
00092 if (range == 0)
00093 {
00094 Usecode_value u(0);
00095 return(u);
00096 }
00097 Usecode_value u=(1 + (rand() % range));
00098 return(u);
00099 }
00100
00101 USECODE_INTRINSIC(execute_usecode_array)
00102 {
00103 COUT("Executing intrinsic 1");
00104
00105 create_script(parms[0], parms[1], 1);
00106
00107 Usecode_value u(1);
00108 return(u);
00109 }
00110
00111 USECODE_INTRINSIC(delayed_execute_usecode_array)
00112 {
00113
00114
00115 if (Game::get_game_type() == BLACK_GATE &&
00116 event == internal_exec && parms[1].get_array_size() == 3 &&
00117 parms[1].get_elem(2).get_int_value() == 0x6f7)
00118 return(no_ret);
00119 int delay = parms[2].get_int_value();
00120 create_script(parms[0], parms[1], delay*gwin->get_std_delay());
00121 COUT("Executing intrinsic 2");
00122
00123 Usecode_value u(1);
00124 return(u);
00125 }
00126
00127 USECODE_INTRINSIC(show_npc_face)
00128 {
00129 show_npc_face(parms[0], parms[1]);
00130 return(no_ret);
00131 }
00132
00133 USECODE_INTRINSIC(remove_npc_face)
00134 {
00135 remove_npc_face(parms[0]);
00136 return(no_ret);
00137 }
00138
00139 USECODE_INTRINSIC(add_answer)
00140 {
00141 conv->add_answer(parms[0]);
00142
00143 return(no_ret);
00144 }
00145
00146 USECODE_INTRINSIC(remove_answer)
00147 {
00148 conv->remove_answer(parms[0]);
00149
00150
00151 return(no_ret);
00152 }
00153
00154 USECODE_INTRINSIC(push_answers)
00155 {
00156 conv->push_answers();
00157 return(no_ret);
00158 }
00159
00160 USECODE_INTRINSIC(pop_answers)
00161 {
00162 if(!conv->stack_empty())
00163 {
00164 conv->pop_answers();
00165 user_choice = 0;
00166 }
00167 return(no_ret);
00168 }
00169
00170 USECODE_INTRINSIC(clear_answers)
00171 {
00172 conv->clear_answers();
00173 return(no_ret);
00174 }
00175
00176 USECODE_INTRINSIC(select_from_menu)
00177 {
00178 user_choice = 0;
00179 const char *choice = get_user_choice();
00180 user_choice = 0;
00181 Usecode_value u(choice);
00182 return(u);
00183 }
00184
00185 USECODE_INTRINSIC(select_from_menu2)
00186 {
00187
00188 user_choice = 0;
00189 Usecode_value val(get_user_choice_num() + 1);
00190 user_choice = 0;
00191 return(val);
00192 }
00193
00194 USECODE_INTRINSIC(input_numeric_value)
00195 {
00196
00197 Usecode_value ret(gumpman->prompt_for_number(
00198 parms[0].get_int_value(), parms[1].get_int_value(),
00199 parms[2].get_int_value(), parms[3].get_int_value(), conv));
00200 conv->clear_text_pending();
00201 return(ret);
00202 }
00203
00204 USECODE_INTRINSIC(set_item_shape)
00205 {
00206
00207 set_item_shape(parms[0], parms[1]);
00208 return(no_ret);
00209 }
00210
00211 USECODE_INTRINSIC(find_nearest)
00212 {
00213
00214 Usecode_value u(find_nearest(parms[0], parms[1], parms[2]));
00215 return(u);
00216 }
00217
00218 USECODE_INTRINSIC(die_roll)
00219 {
00220
00221 int low = parms[0].get_int_value();
00222 int high = parms[1].get_int_value();
00223 if (low > high)
00224 {
00225 int tmp = low;
00226 low = high;
00227 high = tmp;
00228 }
00229 int val = (rand() % (high - low + 1)) + low;
00230 Usecode_value u(val);
00231 return(u);
00232 }
00233
00234 USECODE_INTRINSIC(get_item_shape)
00235 {
00236 Game_object *item = get_item(parms[0]);
00237
00238 Actor *act = as_actor(item);
00239 return Usecode_value(item == 0 ? 0 :
00240 (act ? act->get_shape_real() : item->get_shapenum()));
00241 }
00242
00243 USECODE_INTRINSIC(get_item_frame)
00244 {
00245
00246 Game_object *item = get_item(parms[0]);
00247
00248 return Usecode_value(item == 0 ? 0 : item->get_framenum()&31);
00249 }
00250
00251 USECODE_INTRINSIC(set_item_frame)
00252 {
00253
00254 set_item_frame(get_item(parms[0]), parms[1].get_int_value());
00255 return(no_ret);
00256 }
00257
00258 USECODE_INTRINSIC(get_item_quality)
00259 {
00260 Game_object *obj = get_item(parms[0]);
00261 if (!obj)
00262 return Usecode_value(0);
00263 Shape_info& info = obj->get_info();
00264 return Usecode_value(info.has_quality() ? obj->get_quality() : 0);
00265 }
00266
00267 USECODE_INTRINSIC(set_item_quality)
00268 {
00269
00270
00271 int qual = parms[1].get_int_value();
00272 if (qual == c_any_qual)
00273 return Usecode_value(1);
00274 Game_object *obj = get_item(parms[0]);
00275 if (obj)
00276 {
00277 Shape_info& info = obj->get_info();
00278 if (info.has_quality())
00279 {
00280 obj->set_quality((unsigned int) qual);
00281 return Usecode_value(1);
00282 }
00283 }
00284 return Usecode_value(0);
00285 }
00286
00287 USECODE_INTRINSIC(get_item_quantity)
00288 {
00289
00290
00291 Usecode_value ret(0);
00292 Game_object *obj = get_item(parms[0]);
00293 if (obj)
00294 ret = Usecode_value(obj->get_quantity());
00295 return(ret);
00296 }
00297
00298 USECODE_INTRINSIC(set_item_quantity)
00299 {
00300
00301 Usecode_value ret(0);
00302 Game_object *obj = get_item(parms[0]);
00303 int newquant = parms[1].get_int_value();
00304 if (obj && obj->get_info().has_quantity())
00305 {
00306 ret = Usecode_value(1);
00307
00308 if (newquant == 0 && obj->get_cx() == 255)
00309 return ret;
00310 int oldquant = obj->get_quantity();
00311 int delta = newquant - oldquant;
00312
00313 int newdelta = obj->modify_quantity(delta);
00314 }
00315 return(ret);
00316 }
00317
00318 USECODE_INTRINSIC(get_object_position)
00319 {
00320
00321
00322 Game_object *obj = get_item(parms[0]);
00323 Tile_coord c(0, 0, 0);
00324 if (obj)
00325 c = obj->get_outermost()->get_original_tile_coord();
00326 Usecode_value vx(c.tx), vy(c.ty), vz(c.tz);
00327 Usecode_value arr(3, &vx);
00328 arr.put_elem(1, vy);
00329 arr.put_elem(2, vz);
00330 return(arr);
00331 }
00332
00333 USECODE_INTRINSIC(get_distance)
00334 {
00335
00336 Game_object *obj0 = get_item(parms[0]);
00337 Game_object *obj1 = get_item(parms[1]);
00338 Usecode_value u((obj0 && obj1) ?
00339 obj0->get_outermost()->get_tile().distance(
00340 obj1->get_outermost()->get_tile()) : 0);
00341 return(u);
00342 }
00343
00344 USECODE_INTRINSIC(find_direction)
00345 {
00346
00347
00348 Usecode_value u=find_direction(parms[0], parms[1]);
00349 return(u);
00350 }
00351
00352 USECODE_INTRINSIC(get_npc_object)
00353 {
00354
00355 Usecode_value& v = parms[0];
00356 if (v.is_array())
00357 {
00358 int sz = v.get_array_size();
00359 Usecode_value ret(sz, 0);
00360 for (int i = 0; i < sz; i++)
00361 {
00362 Usecode_value elem(get_item(v.get_elem(i)));
00363 ret.put_elem(i, elem);
00364 }
00365 return ret;
00366 }
00367 Game_object *obj = get_item(parms[0]);
00368 Usecode_value u(obj);
00369 return(u);
00370 }
00371
00372 USECODE_INTRINSIC(get_schedule_type)
00373 {
00374
00375 Actor *npc = as_actor(get_item(parms[0]));
00376 if (!npc)
00377 return Usecode_value(0);
00378 Schedule *schedule = npc->get_schedule();
00379 int sched = schedule ? schedule->get_actual_type(npc)
00380 : npc->get_schedule_type();
00381
00382
00383
00384 if (Game::get_game_type() == SERPENT_ISLE &&
00385 npc->get_action() && npc->get_action()->as_usecode_path())
00386
00387 sched = Schedule::walk_to_schedule;
00388 Usecode_value u(sched);
00389 return(u);
00390 }
00391
00392 USECODE_INTRINSIC(set_schedule_type)
00393 {
00394
00395
00396
00397 Actor *npc = as_actor(get_item(parms[0]));
00398 if (npc)
00399 {
00400 int newsched = parms[1].get_int_value();
00401 npc->set_schedule_type(newsched);
00402
00403 if (npc == gwin->get_main_actor() && gwin->in_combat() &&
00404 newsched != Schedule::combat)
00405
00406 {
00407 Audio::get_ptr()->stop_music();
00408 gwin->toggle_combat();
00409 }
00410 }
00411 return(no_ret);
00412 }
00413
00414 USECODE_INTRINSIC(add_to_party)
00415 {
00416
00417 Actor *npc = as_actor(get_item(parms[0]));
00418 if (!partyman->add_to_party(npc))
00419 return no_ret;
00420 npc->set_schedule_type(Schedule::follow_avatar);
00421
00422 return no_ret;
00423 }
00424
00425 USECODE_INTRINSIC(remove_from_party)
00426 {
00427
00428 Game_object *npc = get_item(parms[0]);
00429 partyman->remove_from_party(as_actor(npc));
00430 return no_ret;
00431 }
00432
00433 USECODE_INTRINSIC(get_npc_prop)
00434 {
00435
00436
00437 Actor *npc = as_actor(get_item(parms[0]));
00438 Usecode_value u(npc ?
00439 npc->get_property(parms[1].get_int_value()) : 0);
00440 return(u);
00441 }
00442
00443 USECODE_INTRINSIC(set_npc_prop)
00444 {
00445
00446 Actor *npc = as_actor(get_item(parms[0]));
00447 if (npc)
00448 {
00449 int prop = parms[1].get_int_value();
00450 npc->set_property(prop, npc->get_property(prop) +
00451 parms[2].get_int_value());
00452 return Usecode_value(1);
00453 }
00454 return Usecode_value(0);
00455 }
00456
00457 USECODE_INTRINSIC(get_avatar_ref)
00458 {
00459
00460 Usecode_value u(gwin->get_main_actor());
00461 return(u);
00462 }
00463
00464 USECODE_INTRINSIC(get_party_list)
00465 {
00466
00467 Usecode_value u(get_party());
00468 return(u);
00469 }
00470
00471 USECODE_INTRINSIC(create_new_object)
00472 {
00473
00474
00475 int shapenum = parms[0].get_int_value();
00476
00477 Game_object *obj;
00478 Shape_info& info = ShapeID::get_info(shapenum);
00479 modified_map = true;
00480
00481 if (info.get_monster_info() || info.is_npc())
00482 {
00483
00484
00485 Monster_actor *monster = Monster_actor::create(shapenum,
00486 Tile_coord(-1, -1, -1), Schedule::wait,
00487 (int) Actor::neutral, true, false);
00488
00489 monster->set_alignment((int) Actor::neutral);
00490 gwin->add_dirty(monster);
00491 gwin->add_nearby_npc(monster);
00492 gwin->show();
00493 last_created.push_back(monster);
00494 return Usecode_value(monster);
00495 }
00496 else
00497 {
00498 if (Is_body(shapenum))
00499 {
00500 obj = new Dead_body(shapenum, 0, 0, 0, 0, -1);
00501 }
00502 else
00503 {
00504 obj = gmap->create_ireg_object(shapenum, 0);
00505
00506 obj->set_flag(Obj_flags::okay_to_take);
00507 }
00508 }
00509 obj->set_invalid();
00510 obj->set_flag(Obj_flags::okay_to_take);
00511 last_created.push_back(obj);
00512 Usecode_value u(obj);
00513 return(u);
00514 }
00515
00516 USECODE_INTRINSIC(create_new_object2)
00517 {
00518
00519 Usecode_value ret = UI_create_new_object(event, intrinsic, 1, parms);
00520 if (ret == 0)
00521 return ret;
00522 UI_update_last_created(event, intrinsic, 1, &parms[1]);
00523 return ret;
00524 }
00525
00526 USECODE_INTRINSIC(set_last_created)
00527 {
00528
00529 Game_object *obj = get_item(parms[0]);
00530 modified_map = true;
00531 if (obj)
00532 {
00533 add_dirty(obj);
00534 last_created.push_back(obj);
00535 obj->remove_this(1);
00536 }
00537 Usecode_value u(obj);
00538 return(u);
00539 }
00540
00541 USECODE_INTRINSIC(update_last_created)
00542 {
00543
00544
00545
00546 modified_map = true;
00547 if (last_created.empty())
00548 {
00549 Usecode_value u((Game_object*) NULL);
00550 return(u);
00551 }
00552 Game_object *obj = last_created.back();
00553 last_created.pop_back();
00554 obj->set_invalid();
00555 Usecode_value& arr = parms[0];
00556 int sz = arr.get_array_size();
00557 if (sz == 3 || sz == 2)
00558 {
00559 Tile_coord dest(arr.get_elem(0).get_int_value(),
00560 arr.get_elem(1).get_int_value(),
00561 sz == 3 ? arr.get_elem(2).get_int_value() : 0);
00562 obj->move(dest.tx, dest.ty, dest.tz);
00563 if (GAME_BG) {
00564 Usecode_value u(1);
00565 return u;
00566 } else {
00567 Usecode_value u(obj);
00568 return u;
00569 }
00570
00571 } else if (sz == 1)
00572 {
00573 obj->remove_this();
00574 }
00575 #ifdef DEBUG
00576 else
00577 {
00578 cout << " { Intrinsic 0x26: "; arr.print(cout); cout << endl << "} ";
00579 }
00580 #endif
00581
00582
00583 Usecode_value u(1);
00584 return(u);
00585 }
00586
00587 USECODE_INTRINSIC(get_npc_name)
00588 {
00589
00590 static const char *unknown = "??name??";
00591 Actor *npc;
00592 int cnt = parms[0].get_array_size();
00593 if (cnt)
00594 {
00595 Usecode_value arr(cnt, 0);
00596 for (int i = 0; i < cnt; i++)
00597 {
00598 Game_object *obj = get_item(parms[0].get_elem(i));
00599 npc = as_actor(obj);
00600 std::string namestr = npc ? npc->get_npc_name()
00601 : obj->get_name();
00602 Usecode_value v(namestr.c_str());
00603 arr.put_elem(i, v);
00604 }
00605 return(arr);
00606 }
00607 Game_object *obj = get_item(parms[0]);
00608 std::string namestr;
00609 if (obj)
00610 {
00611 npc = as_actor(obj);
00612 namestr = npc ? npc->get_npc_name() : obj->get_name();
00613 }
00614 else
00615 namestr = unknown;
00616 Usecode_value u(namestr.c_str());
00617 return(u);
00618 }
00619
00620 USECODE_INTRINSIC(count_objects)
00621 {
00622
00623
00624
00625
00626 Usecode_value u(count_objects(parms[0], parms[1], parms[2], parms[3]));
00627 return(u);
00628 }
00629
00630 USECODE_INTRINSIC(find_object)
00631 {
00632
00633
00634 int shnum = parms[1].get_int_value(),
00635 qual = parms[2].get_int_value(),
00636 frnum = parms[3].get_int_value();
00637 if (parms[0].get_array_size() == 3)
00638 {
00639 Game_object_vector vec;
00640 Game_object::find_nearby(vec,
00641 Tile_coord(parms[0].get_elem(0).get_int_value(),
00642 parms[0].get_elem(1).get_int_value(),
00643 parms[0].get_elem(2).get_int_value()),
00644 shnum, 1, 0, qual, frnum);
00645 if (vec.empty())
00646 return Usecode_value((Game_object *) 0);
00647 else
00648 return Usecode_value(vec.front());
00649 }
00650 int oval = parms[0].get_int_value();
00651 if (oval != -357)
00652 {
00653 Game_object *obj = get_item(parms[0]);
00654 if (!obj)
00655 return Usecode_value((Game_object*) NULL);
00656 Game_object *f = obj->find_item(shnum, qual, frnum);
00657 return Usecode_value(f);
00658 }
00659
00660 Usecode_value party = get_party();
00661 int cnt = party.get_array_size();
00662 for (int i = 0; i < cnt; i++)
00663 {
00664 Game_object *obj = get_item(party.get_elem(i));
00665 if (obj)
00666 {
00667 Game_object *f = obj->find_item(shnum, qual, frnum);
00668 if (f)
00669 return Usecode_value(f);
00670 }
00671 }
00672 return Usecode_value((Game_object*) NULL);
00673 }
00674
00675 USECODE_INTRINSIC(get_cont_items)
00676 {
00677
00678
00679 Usecode_value u(get_objects(parms[0], parms[1], parms[2], parms[3]));
00680 return(u);
00681 }
00682
00683
00684 USECODE_INTRINSIC(remove_party_items)
00685 {
00686
00687 return remove_party_items(parms[0], parms[1], parms[2],
00688 parms[3], parms[4]);
00689 }
00690
00691 USECODE_INTRINSIC(add_party_items)
00692 {
00693
00694
00695 Usecode_value u(add_party_items(parms[0], parms[1], parms[2],
00696 parms[3], parms[4]));
00697 return(u);
00698 }
00699
00700 USECODE_INTRINSIC(play_music)
00701 {
00702
00703
00704 #ifdef DEBUG
00705 cout << "Music request in usecode" << endl;
00706 cout << "Parameter data follows" << endl;
00707 cout << "0: " << ((parms[0].get_int_value()>>8)&0xff) << " " << ((parms[0].get_int_value())&0xff) << endl;
00708 cout << "1: " << ((parms[1].get_int_value()>>8)&0x01) << " " << ((parms[1].get_int_value())&0x01) << endl;
00709 #endif
00710 int track = parms[0].get_int_value()&0xff;
00711 if (track == 0xff)
00712 Audio::get_ptr()->cancel_streams();
00713 else
00714 {
00715 Audio::get_ptr()->start_music(track,
00716 (parms[0].get_int_value()>>8)&0x01);
00717
00718 Game_object *obj = get_item(parms[1]);
00719 if (obj)
00720 gwin->get_effects()->add_effect(
00721 new Sprites_effect(24, obj, 0, 0, -2, -2));
00722 }
00723 return(no_ret);
00724 }
00725
00726 USECODE_INTRINSIC(npc_nearby)
00727 {
00728
00729 Game_object *npc = get_item(parms[0]);
00730 int is_near = (npc != 0 &&
00731 npc->get_tile().distance(gwin->get_main_actor()->get_tile())
00732 < 12 &&
00733
00734 !npc->get_flag(Obj_flags::asleep));
00735 Usecode_value u(is_near);
00736 return(u);
00737 }
00738
00739 USECODE_INTRINSIC(npc_nearby2)
00740 {
00741
00742
00743 Game_object *npc = get_item(parms[0]);
00744 int is_near = (npc != 0 &&
00745 npc->get_tile().distance(gwin->get_main_actor()->get_tile())
00746 < 40 &&
00747
00748 !npc->get_flag(Obj_flags::asleep));
00749 Usecode_value u(is_near);
00750 return(u);
00751 }
00752
00753 USECODE_INTRINSIC(find_nearby_avatar)
00754 {
00755
00756 Usecode_value av(gwin->get_main_actor());
00757
00758 Usecode_value dist( 192), mask(0);
00759 Usecode_value u(find_nearby(av, parms[0], dist, mask));
00760 return(u);
00761 }
00762
00763 USECODE_INTRINSIC(is_npc)
00764 {
00765
00766 Actor *npc = as_actor(get_item(parms[0]));
00767 Usecode_value u(npc != 0);
00768 return(u);
00769 }
00770
00771 USECODE_INTRINSIC(display_runes)
00772 {
00773
00774
00775 int cnt = parms[1].get_array_size();
00776 if (!cnt)
00777 cnt = 1;
00778 Sign_gump *sign = new Sign_gump(parms[0].get_int_value(), cnt);
00779 bool si = Game::get_game_type()== SERPENT_ISLE;
00780 for (int i = 0; i < cnt; i++)
00781 {
00782 Usecode_value& lval = !i ? parms[1].get_elem0()
00783 : parms[1].get_elem(i);
00784 const char *str = lval.get_str_value();
00785 #if 0
00786 if (si)
00787 {
00788 char *newstr = strdup(str);
00789 for (char *ptr = newstr; *ptr; ptr++)
00790 if (*ptr >= 'A' && *ptr <= 'Z')
00791 *ptr += 0x20;
00792 sign->add_text(i, newstr);
00793 delete newstr;
00794 }
00795 else
00796 #endif
00797 sign->add_text(i, str);
00798 }
00799 int x, y;
00800 Get_click(x, y, Mouse::hand, 0, false, sign);
00801 delete sign;
00802 gwin->paint();
00803 return(no_ret);
00804 }
00805
00806 USECODE_INTRINSIC(click_on_item)
00807 {
00808
00809
00810 Game_object *obj;
00811 Tile_coord t;
00812
00813
00814 if (intercept_item) {
00815 obj = intercept_item;
00816 intercept_item = 0;
00817 t = obj->get_tile();
00818
00819
00820 } else if (event == weapon && caller_item)
00821 {
00822
00823
00824
00825
00826
00827 Actor *npc = as_actor(caller_item);
00828 if (npc == gwin->get_main_actor() && npc->get_target())
00829 obj = npc->get_target();
00830 else
00831 obj = caller_item;
00832 t = obj->get_tile();
00833 }
00834 else
00835 {
00836 int x, y;
00837 if (!Get_click(x, y, Mouse::greenselect, 0, true))
00838 return Usecode_value(0);
00839
00840 t = Tile_coord(gwin->get_scrolltx() + x/c_tilesize,
00841 gwin->get_scrollty() + y/c_tilesize, 0);
00842
00843 Gump *gump = gumpman->find_gump(x, y);
00844 if (gump)
00845 {
00846 obj = gump->find_object(x, y);
00847 if (!obj) obj = gump->find_actor(x, y);
00848 }
00849 else
00850 {
00851 obj = gwin->find_object(x, y);
00852 if (obj)
00853 t = obj->get_tile();
00854 }
00855 }
00856 Usecode_value oval(obj);
00857 Usecode_value ret(4, &oval);
00858 Usecode_value xval(t.tx), yval(t.ty), zval(t.tz);
00859 ret.put_elem(1, xval);
00860 ret.put_elem(2, yval);
00861 ret.put_elem(3, zval);
00862 return (ret);
00863 }
00864
00865
00866
00867
00868 USECODE_INTRINSIC(set_intercept_item)
00869 {
00870 intercept_item = get_item(parms[0]);
00871 return no_ret;
00872 }
00873
00874 USECODE_INTRINSIC(find_nearby)
00875 {
00876
00877 Usecode_value u(find_nearby(parms[0], parms[1], parms[2], parms[3]));
00878 return(u);
00879 }
00880
00881 USECODE_INTRINSIC(give_last_created)
00882 {
00883
00884 Game_object *cont = get_item(parms[0]);
00885 int ret = 0;
00886 if (cont && !last_created.empty())
00887 {
00888
00889 Game_object *obj = last_created.back();
00890
00891 ret = cont->add(obj, 1);
00892 if (ret)
00893
00894 last_created.pop_back();
00895 }
00896 Usecode_value u(ret);
00897 return(u);
00898 }
00899
00900 USECODE_INTRINSIC(is_dead)
00901 {
00902
00903 Actor *npc = as_actor(get_item(parms[0]));
00904 Usecode_value u(npc && npc->is_dead());
00905 return(u);
00906 }
00907
00908 USECODE_INTRINSIC(game_hour)
00909 {
00910
00911 Usecode_value u(gclock->get_hour());
00912 return(u);
00913 }
00914
00915 USECODE_INTRINSIC(game_minute)
00916 {
00917
00918 Usecode_value u(gclock->get_minute());
00919 return(u);
00920 }
00921
00922 USECODE_INTRINSIC(get_npc_number)
00923 {
00924
00925
00926 Actor *npc = as_actor(get_item(parms[0]));
00927 if (npc == gwin->get_main_actor())
00928 {
00929 Usecode_value u(-356);
00930 return(u);
00931 }
00932 int num = npc ? npc->get_npc_num() : 0;
00933 Usecode_value u(-num);
00934 return(u);
00935 }
00936
00937 USECODE_INTRINSIC(part_of_day)
00938 {
00939
00940 Usecode_value u(gclock->get_hour()/3);
00941 return(u);
00942 }
00943
00944 USECODE_INTRINSIC(get_alignment)
00945 {
00946
00947 Actor *npc = as_actor(get_item(parms[0]));
00948 Usecode_value u(npc ? npc->get_alignment() : 0);
00949 return(u);
00950 }
00951
00952 USECODE_INTRINSIC(set_alignment)
00953 {
00954
00955
00956 Actor *npc = as_actor(get_item(parms[0]));
00957 int val = parms[1].get_int_value();
00958 if (npc)
00959 {
00960 int oldalign = npc->get_alignment();
00961 npc->set_alignment(val);
00962 if (oldalign != val)
00963 npc->set_target(0);
00964
00965 if (npc->get_attack_mode() == Actor::flee)
00966 npc->set_attack_mode(Actor::nearest);
00967 }
00968 return(no_ret);
00969 }
00970
00971 USECODE_INTRINSIC(move_object)
00972 {
00973
00974 Usecode_value& p = parms[1];
00975 Tile_coord tile(p.get_elem(0).get_int_value(),
00976 p.get_elem(1).get_int_value(),
00977 p.get_elem(2).get_int_value());
00978 Actor *ava = gwin->get_main_actor();
00979 modified_map = true;
00980 if (parms[0].get_int_value() == -357)
00981 {
00982
00983
00984 gwin->teleport_party(tile, Game::get_game_type() ==
00985 SERPENT_ISLE && frame->function->id == 0x7df &&
00986 caller_item->get_quality() == 0xcf);
00987 return (no_ret);
00988 }
00989 Game_object *obj = get_item(parms[0]);
00990 if (!obj)
00991 return (no_ret);
00992 Tile_coord oldpos = obj->get_tile();
00993 obj->move(tile.tx, tile.ty, tile.tz);
00994 Actor *act = as_actor(obj);
00995 if (act)
00996 {
00997 act->set_action(0);
00998 if (act == ava)
00999 {
01000
01001 gwin->center_view(tile);
01002 Map_chunk::try_all_eggs(ava, tile.tx,
01003 tile.ty, tile.tz, oldpos.tx, oldpos.ty);
01004 }
01005
01006 else if (ava->distance(act) < gwin->get_width()/c_tilesize)
01007 {
01008 Npc_actor *npc = act->as_npc();
01009 if (npc) gwin->add_nearby_npc(npc);
01010 }
01011 }
01012 return(no_ret);
01013 }
01014
01015 USECODE_INTRINSIC(remove_npc)
01016 {
01017
01018 Actor *npc = as_actor(get_item(parms[0]));
01019 if (npc)
01020 {
01021 modified_map = true;
01022
01023 npc->set_schedule_type(Schedule::wait);
01024 gwin->add_dirty(npc);
01025 npc->remove_this(1);
01026 }
01027 return (no_ret);
01028 }
01029
01030 USECODE_INTRINSIC(item_say)
01031 {
01032
01033 if (!conv->is_npc_text_pending())
01034 item_say(parms[0], parms[1]);
01035 return(no_ret);
01036 }
01037
01038 USECODE_INTRINSIC(clear_item_say)
01039 {
01040
01041 Game_object *item = get_item(parms[0]);
01042 if (item)
01043 gwin->get_effects()->remove_text_effect(item);
01044 return(no_ret);
01045 }
01046
01047 USECODE_INTRINSIC(projectile_effect)
01048 {
01049
01050
01051
01052 Game_object *from = get_item(parms[0]),
01053 *to = get_item(parms[1]);
01054 if (!from || !to)
01055 return Usecode_value(0);
01056 Actor *attacker = as_actor(from);
01057 if (!attacker)
01058 return Usecode_value(0);
01059 int shnum = parms[2].get_int_value();
01060 gwin->get_effects()->add_effect(
01061 new Projectile_effect(attacker, to, shnum));
01062
01063 return Usecode_value(0);
01064 }
01065
01066 USECODE_INTRINSIC(get_lift)
01067 {
01068
01069 Game_object *obj = get_item(parms[0]);
01070 Usecode_value u(obj ? Usecode_value(obj->get_lift())
01071 : Usecode_value(0));
01072 return(u);
01073 }
01074
01075 USECODE_INTRINSIC(set_lift)
01076 {
01077
01078 Game_object *obj = get_item(parms[0]);
01079 if (obj)
01080 {
01081 Tile_coord t = obj->get_tile();
01082 int lift = parms[1].get_int_value();
01083 if (lift >= 0 && lift < 20)
01084 obj->move(t.tx, t.ty, lift);
01085 gwin->paint();
01086 gwin->show();
01087 modified_map = true;
01088 }
01089 return(no_ret);
01090 }
01091
01092 USECODE_INTRINSIC(get_weather)
01093 {
01094
01095 return Usecode_value(gwin->get_effects()->get_weather());
01096 }
01097
01098 USECODE_INTRINSIC(set_weather)
01099 {
01100
01101 Egg_object::set_weather(parms[0].get_int_value());
01102 return no_ret;
01103 }
01104
01105
01106 USECODE_INTRINSIC(sit_down)
01107 {
01108
01109 Game_object *nobj = get_item(parms[0]);
01110 Actor *npc = as_actor(nobj);
01111 if (!npc)
01112 return (no_ret);
01113 Game_object *chair = get_item(parms[1]);
01114 if (!chair)
01115 return (no_ret);
01116 npc->set_schedule_type(Schedule::sit, new Sit_schedule(npc, chair));
01117 return(no_ret);
01118 }
01119
01120 USECODE_INTRINSIC(summon)
01121 {
01122
01123
01124 int shapenum = parms[0].get_int_value();
01125 Monster_info *info = ShapeID::get_info(shapenum).get_monster_info();
01126 if (!info)
01127 return Usecode_value(0);
01128 Tile_coord start = gwin->get_main_actor()->get_tile();
01129 Tile_coord dest = Map_chunk::find_spot(start, 5, shapenum, 0, 1,
01130 -1, gwin->is_main_actor_inside() ?
01131 Map_chunk::inside : Map_chunk::outside);
01132 if (dest.tx == -1)
01133 return Usecode_value(0);
01134 Monster_actor *monst = Monster_actor::create(shapenum, dest,
01135 Schedule::combat, Actor::friendly);
01136 return Usecode_value(monst);
01137 }
01138
01139
01140
01141
01142 class Paint_centered : public Paintable, public Game_singletons
01143 {
01144 protected:
01145 ShapeID *sid;
01146 int x, y;
01147 public:
01148 Paint_centered(ShapeID *si) : sid(si)
01149 {
01150 Shape_frame *s = sid->get_shape();
01151
01152 x = (gwin->get_width() - s->get_width())/2 + s->get_xleft();
01153 y = (gwin->get_height() - s->get_height())/2 + s->get_yabove();
01154 }
01155 virtual void paint()
01156 {
01157 sid->paint_shape(x, y);
01158 }
01159 };
01160
01161
01162
01163 class Paint_map : public Paint_centered
01164 {
01165 bool show_loc;
01166 public:
01167 Paint_map(ShapeID *s, bool loc) : Paint_centered(s), show_loc(loc)
01168 { }
01169 virtual void paint()
01170 {
01171 Paint_centered::paint();
01172 if (show_loc)
01173 {
01174 int xx, yy;
01175 Tile_coord t = gwin->get_main_actor()->get_tile();
01176 if (Game::get_game_type()==BLACK_GATE) {
01177 xx = (int)(t.tx/16.05 + 5 + 0.5);
01178 yy = (int)(t.ty/15.95 + 4 + 0.5);
01179 } else if (Game::get_game_type()==SERPENT_ISLE) {
01180 xx = (int)(t.tx/16.0 + 18 + 0.5);
01181 yy = (int)(t.ty/16.0 + 9.4 + 0.5);
01182 }
01183 Shape_frame *s = sid->get_shape();
01184 xx += x - s->get_xleft();
01185 yy += y - s->get_yabove();
01186 gwin->get_win()->fill8(255, 1, 5, xx, yy - 2);
01187 gwin->get_win()->fill8(255, 5, 1, xx - 2, yy);
01188 }
01189 }
01190 };
01191
01192 USECODE_INTRINSIC(display_map)
01193 {
01194
01195
01196 Usecode_value v_357(-357), v650(650), v_359(-359);
01197 long sextants=count_objects(v_357, v650, v_359, v_359).get_int_value();
01198 bool loc = !gwin->is_main_actor_inside() && (sextants > 0);
01199
01200 ShapeID msid(game->get_shape("sprites/map"), 0, SF_SPRITES_VGA);
01201 Paint_map map(&msid, loc);
01202
01203 int xx, yy;
01204 Get_click(xx, yy, Mouse::hand, 0, false, &map);
01205 gwin->paint();
01206 return(no_ret);
01207 }
01208
01209 USECODE_INTRINSIC(si_display_map)
01210 {
01211 int mapnum = parms[0].get_int_value();
01212 int shapenum;
01213
01214 switch (mapnum) {
01215 case 0: return UI_display_map(event,intrinsic,num_parms,parms);
01216 case 1: shapenum = 57; break;
01217 case 2: shapenum = 58; break;
01218 case 3: shapenum = 59; break;
01219 case 4: shapenum = 60; break;
01220 case 5: shapenum = 52; break;
01221 default: return no_ret;
01222 }
01223
01224
01225
01226
01227 ShapeID msid(shapenum, 0, SF_SPRITES_VGA);
01228 Paint_centered map(&msid);
01229 int xx, yy;
01230 Get_click(xx, yy, Mouse::hand, 0, false, &map);
01231 gwin->paint();
01232
01233 return no_ret;
01234 }
01235
01236 USECODE_INTRINSIC(kill_npc)
01237 {
01238
01239 Game_object *item = get_item(parms[0]);
01240 Actor *npc = as_actor(item);
01241 if (npc)
01242 npc->die(0);
01243 modified_map = true;
01244 return (no_ret);
01245 }
01246
01247 USECODE_INTRINSIC(roll_to_win)
01248 {
01249
01250 int attack = parms[0].get_int_value();
01251 int defend = parms[1].get_int_value();
01252 return Usecode_value((int) Actor::roll_to_win(attack, defend));
01253 }
01254
01255 USECODE_INTRINSIC(set_attack_mode)
01256 {
01257
01258 Actor *npc = as_actor(get_item(parms[0]));
01259 if (npc)
01260 npc->set_attack_mode((Actor::Attack_mode)
01261 parms[1].need_int_value());
01262 return (no_ret);
01263 }
01264
01265 USECODE_INTRINSIC(get_attack_mode)
01266 {
01267
01268 Actor *npc = as_actor(get_item(parms[0]));
01269 if (npc)
01270 return Usecode_value((int) npc->get_attack_mode());
01271 return Usecode_value(0);
01272 }
01273
01274 USECODE_INTRINSIC(set_opponent)
01275 {
01276
01277 Actor *npc = as_actor(get_item(parms[0]));
01278 Game_object *opponent = get_item(parms[1]);
01279 if (npc && opponent)
01280 npc->set_target(opponent);
01281 return (no_ret);
01282 }
01283
01284 USECODE_INTRINSIC(clone)
01285 {
01286
01287 Actor *npc = as_actor(get_item(parms[0]));
01288 if (npc)
01289 {
01290 modified_map = true;
01291 npc->set_alignment(Actor::friendly);
01292 npc->set_schedule_type(Schedule::combat);
01293 return Usecode_value(npc->clone());
01294 }
01295 return Usecode_value(0);
01296 }
01297
01298 USECODE_INTRINSIC(get_oppressor)
01299 {
01300
01301 Actor *npc = as_actor(get_item(parms[0]));
01302 return Usecode_value(npc ? npc->get_oppressor() : 0);
01303 }
01304
01305 USECODE_INTRINSIC(set_oppressor)
01306 {
01307
01308 Actor *npc = as_actor(get_item(parms[0]));
01309 Actor *opp = as_actor(get_item(parms[1]));
01310 if (npc && opp)
01311 {
01312 if (opp == gwin->get_main_actor())
01313 npc->set_oppressor(0);
01314 else
01315 npc->set_oppressor(opp->get_npc_num());
01316
01317 npc->set_target(opp);
01318 }
01319 return no_ret;
01320 }
01321
01322 USECODE_INTRINSIC(get_weapon)
01323 {
01324
01325 Actor *npc = as_actor(get_item(parms[0]));
01326 if (npc)
01327 {
01328 int shape, points;
01329 if (npc->get_weapon(points, shape))
01330 return Usecode_value(shape);
01331 }
01332 return Usecode_value(0);
01333 }
01334
01335 USECODE_INTRINSIC(display_area)
01336 {
01337
01338 int size = parms[0].get_array_size();
01339 if (size >= 3)
01340 {
01341 int tx = parms[0].get_elem(0).get_int_value();
01342 int ty = parms[0].get_elem(1).get_int_value();
01343 int unknown = parms[0].get_elem(2).get_int_value();
01344
01345 int tw = gwin->get_width()/c_tilesize,
01346 th = gwin->get_height()/c_tilesize;
01347 gwin->clear_screen();
01348 Shape_frame *sprite = ShapeID(10, 0, SF_SPRITES_VGA).get_shape();
01349
01350 int topx = (gwin->get_width() - sprite->get_width())/2,
01351 topy = (gwin->get_height() - sprite->get_height())/2;
01352
01353 int x = topx, y = topy, w = sprite->get_width(),
01354 h = sprite->get_height();
01355 if (w > gwin->get_width())
01356 { x = 0; w = gwin->get_width(); }
01357 if (h > gwin->get_height())
01358 { y = 0; h = gwin->get_height(); }
01359 int save_dungeon = gwin->is_in_dungeon();
01360 gwin->set_in_dungeon(0);
01361
01362 gwin->paint_map_at_tile(x, y, w, h, tx - tw/2, ty - th/2, 4);
01363
01364
01365 sman->paint_shape(topx + sprite->get_xleft(),
01366 topy + sprite->get_yabove(), sprite, 1);
01367 gwin->set_in_dungeon(save_dungeon);
01368 gwin->show();
01369
01370 Get_click(x, y, Mouse::hand);
01371 gwin->paint();
01372 }
01373 return (no_ret);
01374 }
01375
01376 USECODE_INTRINSIC(wizard_eye)
01377 {
01378
01379 extern void Wizard_eye(long);
01380
01381 Wizard_eye(parms[0].get_int_value()*(3*gwin->get_std_delay())/2);
01382 return no_ret;
01383 }
01384
01385 USECODE_INTRINSIC(resurrect)
01386 {
01387
01388 Game_object *body = get_item(parms[0]);
01389 int npc_num = body ? body->get_live_npc_num() : -1;
01390 if (npc_num < 0)
01391 return Usecode_value((Game_object*) NULL);
01392 Actor *actor = gwin->get_npc(npc_num);
01393 if (actor)
01394 {
01395 Usecode_script *scr = new Usecode_script(body);
01396 (*scr) << Ucscript::resurrect;
01397 scr->start();
01398 modified_map = true;
01399 }
01400 return Usecode_value(actor);
01401 }
01402
01403 USECODE_INTRINSIC(get_body_npc)
01404 {
01405
01406 Game_object *obj = get_item(parms[0]);
01407 int num = obj ? obj->get_live_npc_num() : -1;
01408 return Usecode_value(num > 0 ? -num : 0);
01409 }
01410
01411 USECODE_INTRINSIC(add_spell)
01412 {
01413
01414
01415 Game_object *obj = get_item(parms[2]);
01416 if (!obj || obj->get_info().get_shape_class() != Shape_info::spellbook)
01417 return Usecode_value(0);
01418 Spellbook_object *book = (Spellbook_object *) (obj);
01419 if (!book)
01420 {
01421 cout << "Add_spell - Not a spellbook!" << endl;
01422 return Usecode_value(0);
01423 }
01424 return Usecode_value(book->add_spell(parms[0].get_int_value()));
01425 }
01426
01427 USECODE_INTRINSIC(sprite_effect)
01428 {
01429
01430
01431
01432 gwin->get_effects()->add_effect(
01433 new Sprites_effect(parms[0].get_int_value(),
01434 Tile_coord(parms[1].get_int_value(), parms[2].get_int_value(),
01435 0),
01436 parms[3].get_int_value(), parms[4].get_int_value()));
01437 return(no_ret);
01438 }
01439
01440 USECODE_INTRINSIC(obj_sprite_effect)
01441 {
01442
01443
01444 Game_object *obj = get_item(parms[0]);
01445 if (obj)
01446
01447 gwin->get_effects()->add_effect(
01448 new Sprites_effect(parms[1].get_int_value(), obj,
01449 -parms[2].get_int_value(), -parms[3].get_int_value(),
01450 parms[4].get_int_value(), parms[5].get_int_value()));
01451 return(no_ret);
01452 }
01453
01454 USECODE_INTRINSIC(explode)
01455 {
01456
01457 Game_object *exp = get_item(parms[1]);
01458 if (!exp)
01459 return Usecode_value(0);
01460
01461 Tile_coord pos = exp->get_outermost()->get_tile();
01462
01463 gwin->get_effects()->add_effect(new Explosion_effect(pos, exp));
01464 return Usecode_value(1);
01465 }
01466
01467 USECODE_INTRINSIC(book_mode)
01468 {
01469
01470 Text_gump *gump;
01471 Game_object *obj = get_item(parms[0]);
01472 if (!obj)
01473 {
01474 return(no_ret);
01475 }
01476
01477
01478 bool do_serp = gwin->get_main_actor()->get_flag(Obj_flags::read) == false;
01479
01480 if (obj->get_shapenum() == 707)
01481 gump = new Scroll_gump(do_serp);
01482 else if (obj->get_shapenum() == 705)
01483 gump = new Book_gump(do_serp);
01484 else if (obj->get_shapenum() == 797)
01485 gump = new Scroll_gump();
01486 else
01487 gump = new Book_gump();
01488 set_book(gump);
01489 return(no_ret);
01490 }
01491
01492 USECODE_INTRINSIC(stop_time)
01493 {
01494
01495 int length = parms[0].get_int_value();
01496 gwin->set_time_stopped(length*250);
01497 return no_ret;
01498 }
01499
01500 USECODE_INTRINSIC(cause_light)
01501 {
01502
01503
01504 gwin->add_special_light(parms[0].get_int_value());
01505 return no_ret;
01506 }
01507
01508 USECODE_INTRINSIC(get_barge)
01509 {
01510
01511
01512 Game_object *obj = get_item(parms[0]);
01513 if (!obj)
01514 return Usecode_value((Game_object*) NULL);
01515 return Usecode_value(Get_barge(obj));
01516 }
01517
01518 USECODE_INTRINSIC(earthquake)
01519 {
01520 int len = parms[0].get_int_value();
01521 gwin->get_tqueue()->add(Game::get_ticks() + 10,
01522 new Earthquake(len), (long) this);
01523 return(no_ret);
01524 }
01525
01526 USECODE_INTRINSIC(is_pc_female)
01527 {
01528
01529 Usecode_value u(gwin->get_main_actor()->get_type_flag(Actor::tf_sex));
01530 return(u);
01531 }
01532
01533 USECODE_INTRINSIC(armageddon)
01534 {
01535 int cnt = gwin->get_num_npcs();
01536 Rectangle screen = gwin->get_win_tile_rect();
01537 for (int i = 1; i < cnt; i++)
01538 {
01539 Actor *npc = gwin->get_npc(i);
01540 if (npc && i != 26 && i != 23 && npc->get_shapenum() != 506 &&
01541 !npc->is_dead())
01542 {
01543 const char *text[] = {"Aiiiieee!", "Noooo!", "#!?*#%!"};
01544 const int numtext = sizeof(text)/sizeof(text[0]);
01545 Tile_coord loc = npc->get_tile();
01546 if (screen.has_point(loc.tx, loc.ty))
01547 npc->say(text[rand()%numtext]);
01548 npc->die(0);
01549 }
01550 }
01551 Actor_vector vec;
01552 gwin->get_main_actor()->find_nearby_actors(vec, c_any_shapenum, 40);
01553 for (Actor_vector::const_iterator it = vec.begin(); it != vec.end();
01554 ++it)
01555 {
01556 Actor *act = *it;
01557 if (act->is_monster())
01558 act->die(gwin->get_main_actor());
01559 }
01560 gwin->armageddon = true;
01561 return no_ret;
01562 }
01563
01564 USECODE_INTRINSIC(halt_scheduled)
01565 {
01566
01567 Game_object *obj = get_item(parms[0]);
01568 if (obj)
01569 Usecode_script::terminate(obj);
01570 return(no_ret);
01571 }
01572
01573 USECODE_INTRINSIC(lightning)
01574 {
01575
01576 gwin->get_effects()->add_effect(new Lightning_effect(1000));
01577 return no_ret;
01578 }
01579
01580 USECODE_INTRINSIC(get_array_size)
01581 {
01582 int cnt;
01583 if (parms[0].is_array())
01584 cnt = parms[0].get_array_size();
01585 else
01586 cnt = 1;
01587 Usecode_value u(cnt);
01588 return(u);
01589 }
01590
01591 USECODE_INTRINSIC(mark_virtue_stone)
01592 {
01593 Game_object *obj = get_item(parms[0]);
01594 if (obj->get_info().get_shape_class() == Shape_info::virtue_stone)
01595 {
01596 Virtue_stone_object *vs = (Virtue_stone_object *) (obj);
01597 vs->set_pos(obj->get_outermost()->get_tile());
01598 }
01599 return no_ret;
01600 }
01601
01602 USECODE_INTRINSIC(recall_virtue_stone)
01603 {
01604 Game_object *obj = get_item(parms[0]);
01605 if (obj->get_info().get_shape_class() == Shape_info::virtue_stone)
01606 {
01607 Virtue_stone_object *vs = (Virtue_stone_object *) (obj);
01608 gumpman->close_all_gumps();
01609
01610 if (!obj->get_owner())
01611 {
01612 obj->remove_this(1);
01613 Usecode_value party = get_party();
01614 int cnt = party.get_array_size();
01615 int i;
01616 for (i = 0; i < cnt; i++)
01617 {
01618 Game_object *npc = get_item(party.get_elem(i));
01619 if (npc && npc->add(obj))
01620 break;
01621 }
01622 if (i == cnt)
01623 gwin->get_main_actor()->add(obj, 1);
01624 }
01625 Tile_coord t = vs->get_pos();
01626 if (t.tx > 0 || t.ty > 0)
01627 gwin->teleport_party(t);
01628 }
01629 return no_ret;
01630 }
01631
01632 USECODE_INTRINSIC(apply_damage)
01633 {
01634
01635 int hps = parms[1].get_int_value();
01636 Actor *npc = as_actor(get_item(parms[3]));
01637 if (npc)
01638 npc->reduce_health(hps);
01639 return Usecode_value(1);
01640 }
01641
01642 USECODE_INTRINSIC(is_pc_inside)
01643 {
01644 Usecode_value u(gwin->is_main_actor_inside());
01645 return(u);
01646 }
01647
01648 USECODE_INTRINSIC(get_timer)
01649 {
01650 int tnum = parms[0].get_int_value();
01651 int ret;
01652 if (tnum >= 0 && tnum < (int)(sizeof(timers)/sizeof(timers[0])))
01653
01654 ret = timers[tnum] > 0 ?
01655 (gclock->get_total_hours() - timers[tnum]) : 0;
01656 else
01657 {
01658 cerr << "Attempt to use invalid timer " << tnum << endl;
01659 ret = 0;
01660 }
01661 return Usecode_value(ret);
01662 }
01663
01664 USECODE_INTRINSIC(set_timer)
01665 {
01666 int tnum = parms[0].get_int_value();
01667 if (tnum >= 0 && tnum < (int)(sizeof(timers)/sizeof(timers[0])))
01668 timers[tnum] = gclock->get_total_hours();
01669 else
01670 cerr << "Attempt to use invalid timer " << tnum << endl;
01671 return(no_ret);
01672 }
01673
01674 USECODE_INTRINSIC(wearing_fellowship)
01675 {
01676 Game_object *obj = gwin->get_main_actor()->get_readied(Actor::neck);
01677 if (obj && obj->get_shapenum() == 955 && obj->get_framenum() == 1)
01678 return Usecode_value(1);
01679 else
01680 return Usecode_value(0);
01681 }
01682
01683 USECODE_INTRINSIC(mouse_exists)
01684 {
01685 Usecode_value u(1);
01686 return(u);
01687 }
01688
01689 USECODE_INTRINSIC(get_speech_track)
01690 {
01691
01692 return Usecode_value(speech_track);
01693 }
01694
01695 USECODE_INTRINSIC(flash_mouse)
01696 {
01697
01698 Mouse::Mouse_shapes shape;
01699 switch (parms[0].need_int_value())
01700 {
01701 case 2:
01702 shape = Mouse::outofrange; break;
01703 case 3:
01704 shape = Mouse::outofammo; break;
01705 case 4:
01706 shape = Mouse::tooheavy; break;
01707 case 5:
01708 shape = Mouse::wontfit; break;
01709 case 0:
01710 case 1:
01711 default:
01712 shape = Mouse::redx; break;
01713 }
01714 Mouse::mouse->flash_shape(shape);
01715 return (no_ret);
01716 }
01717
01718 USECODE_INTRINSIC(get_item_frame_rot)
01719 {
01720
01721 Game_object *obj = get_item(parms[0]);
01722 return Usecode_value(obj ? obj->get_framenum() : 0);
01723 }
01724
01725 USECODE_INTRINSIC(set_item_frame_rot)
01726 {
01727 set_item_frame(get_item(parms[0]), parms[1].get_int_value(), 0, 1);
01728 return(no_ret);
01729 }
01730
01731 USECODE_INTRINSIC(on_barge)
01732 {
01733
01734
01735
01736 Barge_object *barge = Get_barge(gwin->get_main_actor());
01737 if (barge)
01738 {
01739 Rectangle foot = barge->get_tile_footprint();
01740 Actor *party[9];
01741 int cnt = gwin->get_party(party, 1);
01742 for (int i = 0; i < cnt; i++)
01743 {
01744 Actor *act = party[i];
01745 Tile_coord t = act->get_tile();
01746 if (!foot.has_point(t.tx, t.ty))
01747 return Usecode_value(0);
01748 }
01749
01750 if (Game::get_game_type() == SERPENT_ISLE)
01751 barge->done();
01752 return Usecode_value(1);
01753 }
01754 return Usecode_value(0);
01755
01756 }
01757
01758 USECODE_INTRINSIC(get_container)
01759 {
01760
01761 Game_object *obj = get_item(parms[0]);
01762 Usecode_value u((Game_object *) NULL);
01763 if (obj)
01764 u = Usecode_value(obj->get_owner());
01765 return(u);
01766 }
01767
01768 USECODE_INTRINSIC(remove_item)
01769 {
01770
01771 remove_item(get_item(parms[0]));
01772 modified_map = true;
01773 return no_ret;
01774 }
01775
01776 USECODE_INTRINSIC(reduce_health)
01777 {
01778
01779 Actor *npc = as_actor(get_item(parms[0]));
01780 if (npc)
01781 npc->reduce_health(parms[1].get_int_value());
01782 return no_ret;
01783 }
01784
01785
01786
01787
01788
01789 static int Get_spot(int ucspot)
01790 {
01791 int spot;
01792 switch (ucspot)
01793 {
01794 case 1:
01795 spot = Actor::lhand; break;
01796 case 2:
01797 spot = Actor::rhand; break;
01798 case 3:
01799 spot = Actor::neck; break;
01800 case 5:
01801 spot = Actor::hands2_spot; break;
01802 case 6:
01803 spot = Actor::lfinger; break;
01804 case 7:
01805 spot = Actor::rfinger; break;
01806 case 9:
01807 spot = Actor::head; break;
01808 case 11:
01809 spot = Actor::belt; break;
01810 default:
01811 cerr << "Readied: spot #" << ucspot <<
01812 " not known yet" << endl;
01813 spot = -1;
01814 }
01815 return spot;
01816 }
01817
01818 USECODE_INTRINSIC(is_readied)
01819 {
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829 Actor *npc = as_actor(get_item(parms[0]));
01830 if (!npc)
01831 return Usecode_value(0);
01832 int where = parms[1].get_int_value();
01833 int shnum = parms[2].get_int_value();
01834 int frnum = parms[3].get_int_value();
01835
01836 int spot = Get_spot(where);
01837 if (spot >= 0)
01838 {
01839 Game_object *obj = npc->get_readied(spot);
01840 if (obj && obj->get_shapenum() == shnum &&
01841 (frnum == c_any_framenum || obj->get_framenum() == frnum))
01842 return Usecode_value(1);
01843 }
01844 return Usecode_value(0);
01845 }
01846
01847 USECODE_INTRINSIC(get_readied)
01848 {
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 Actor *npc = as_actor(get_item(parms[0]));
01860 if (!npc)
01861 return Usecode_value(0);
01862 int where = parms[1].get_int_value();
01863
01864 int spot = Get_spot(where);
01865 if (spot >= 0)
01866 return Usecode_value(npc->get_readied(spot));
01867 return Usecode_value(0);
01868 }
01869
01870 USECODE_INTRINSIC(restart_game)
01871 {
01872
01873
01874 Audio::get_ptr()->stop_music();
01875 quitting_time = QUIT_TIME_RESTART;
01876 return(no_ret);
01877 }
01878
01879 USECODE_INTRINSIC(start_speech)
01880 {
01881
01882 bool okay = false;
01883 speech_track = parms[0].get_int_value();
01884 if (speech_track >= 0)
01885 okay = Audio::get_ptr()->start_speech(speech_track);
01886 if (!okay)
01887 init_conversation();
01888 return(Usecode_value(okay ? 1 : 0));
01889 }
01890
01891 USECODE_INTRINSIC(is_water)
01892 {
01893
01894 int size = parms[0].get_array_size();
01895 if (size >= 3)
01896 {
01897 Tile_coord t(parms[0].get_elem(0).get_int_value(),
01898 parms[0].get_elem(1).get_int_value(),
01899 parms[0].get_elem(2).get_int_value());
01900
01901 int x = (t.tx - gwin->get_scrolltx())*c_tilesize,
01902 y = (t.ty - gwin->get_scrollty())*c_tilesize;
01903 if (t.tz != 0 || gwin->find_object(x, y))
01904 return Usecode_value(0);
01905 ShapeID sid = gwin->get_flat(x, y);
01906 if (sid.is_invalid())
01907 return Usecode_value(0);
01908 Shape_info& info = sid.get_info();
01909 return Usecode_value(info.is_water());
01910 }
01911 return Usecode_value(0);
01912 }
01913
01914 USECODE_INTRINSIC(run_endgame)
01915 {
01916 Audio::get_ptr()->stop_sound_effects();
01917 game->end_game(parms[0].get_int_value() != 0);
01918
01919 if(parms[0].get_int_value() != 0) {
01920 std::ofstream endgameflg;
01921 U7open(endgameflg, "<SAVEGAME>/endgame.flg");
01922 endgameflg.close();
01923 game->show_credits();
01924 }
01925 quitting_time = QUIT_TIME_YES;
01926 return(no_ret);
01927 }
01928
01929 USECODE_INTRINSIC(fire_cannon)
01930 {
01931
01932
01933 Game_object *cannon = get_item(parms[0]);
01934
01935 int dir = parms[1].get_int_value();
01936 dir = dir/2;
01937 int ball = parms[2].get_int_value();
01938 int dist = parms[3].get_int_value();
01939 int cshape = parms[4].get_int_value();
01940 Tile_coord pos = cannon->get_tile();
01941 short blastoff[8] = {-2, -5, 1, -2, -2, 1, -5, -2};
01942 Tile_coord blastpos = pos + Tile_coord(
01943 blastoff[2*dir], blastoff[2*dir + 1], 0);
01944
01945 gwin->get_effects()->add_effect(new Sprites_effect(5, blastpos));
01946 Tile_coord dest = pos;
01947 switch (dir)
01948 {
01949 case 0: dest.ty -= dist; break;
01950 case 1: dest.tx += dist; break;
01951 case 2: dest.ty += dist; break;
01952 case 3: dest.tx -= dist; break;
01953 }
01954
01955 gwin->get_effects()->add_effect(
01956 new Projectile_effect(blastpos, dest, ball, cshape));
01957 return no_ret;
01958 }
01959
01960 USECODE_INTRINSIC(nap_time)
01961 {
01962
01963 Game_object *bed = get_item(parms[0]);
01964 if (!bed)
01965 return no_ret;
01966
01967 Actor_vector npcs;
01968 int cnt = bed->find_nearby_actors(npcs, c_any_shapenum, 0);
01969 if (cnt > 0)
01970 {
01971 Actor_vector::const_iterator it;
01972 for (it = npcs.begin(); it != npcs.end(); ++it)
01973 {
01974 Game_object *npc = *it;
01975 int zdiff = npc->get_lift() - bed->get_lift();
01976 if (npc != gwin->get_main_actor() &&
01977 (npc->get_framenum()&0xf) == Actor::sleep_frame &&
01978 zdiff <= 2 && zdiff >= -2)
01979 break;
01980 }
01981 if (it != npcs.end())
01982 {
01983 int party_cnt = partyman->get_count();
01984 int npcnum = party_cnt ? partyman->get_member(
01985 rand()%party_cnt) : 356;
01986 Usecode_value actval(-npcnum), frval(0);
01987 show_npc_face(actval, frval);
01988 conv->show_npc_message(item_names[first_bed_occupied +
01989 rand()%num_bed_occupied]);
01990 remove_npc_face(actval);
01991 gwin->get_main_actor()->set_schedule_type(
01992 Schedule::follow_avatar);
01993 return no_ret;
01994 }
01995 }
01996 Schedule *sched = gwin->get_main_actor()->get_schedule();
01997 if (sched)
01998 sched->set_bed(bed);
01999
02000
02001 Wait_for_arrival(gwin->get_main_actor(), bed->get_tile(),
02002 5000);
02003 call_usecode(0x622, bed, double_click);
02004 return(no_ret);
02005 }
02006
02007 USECODE_INTRINSIC(advance_time)
02008 {
02009
02010 gclock->increment(parms[0].get_int_value()/25);
02011 return(no_ret);
02012 }
02013
02014 USECODE_INTRINSIC(in_usecode)
02015 {
02016
02017
02018 Game_object *obj = get_item(parms[0]);
02019 if (!obj)
02020 return Usecode_value(0);
02021 return Usecode_value(Usecode_script::find(obj) != 0);
02022 }
02023
02024 USECODE_INTRINSIC(call_guards)
02025 {
02026
02027 gwin->call_guards();
02028 return no_ret;
02029 }
02030
02031 USECODE_INTRINSIC(attack_avatar)
02032 {
02033
02034 gwin->attack_avatar();
02035 return no_ret;
02036 }
02037
02038 USECODE_INTRINSIC(path_run_usecode)
02039 {
02040
02041
02042
02043 Usecode_value ava(gwin->get_main_actor());
02044 return Usecode_value(path_run_usecode(ava, parms[0], parms[1],
02045 parms[2], parms[3],
02046
02047 Game::get_game_type() == SERPENT_ISLE));
02048 }
02049
02050 USECODE_INTRINSIC(close_gumps)
02051 {
02052 if (!gwin->is_dragging())
02053 gumpman->close_all_gumps();
02054 return(no_ret);
02055 }
02056
02057 USECODE_INTRINSIC(in_gump_mode)
02058 {
02059
02060 return Usecode_value(gumpman->showing_gumps(true));
02061 }
02062
02063 USECODE_INTRINSIC(is_not_blocked)
02064 {
02065
02066 Usecode_value fail(0);
02067
02068 Usecode_value& pval = parms[0];
02069 if (pval.get_array_size() < 3)
02070 return fail;
02071 Tile_coord tile(pval.get_elem(0).get_int_value(),
02072 pval.get_elem(1).get_int_value(),
02073 pval.get_elem(2).get_int_value());
02074 int shapenum = parms[1].get_int_value();
02075 int framenum = parms[2].get_int_value();
02076
02077 Shape_info& info = ShapeID::get_info(shapenum);
02078 Rectangle footprint(
02079 tile.tx - info.get_3d_xtiles(framenum) + 1,
02080 tile.ty - info.get_3d_ytiles(framenum) + 1,
02081 info.get_3d_xtiles(framenum), info.get_3d_ytiles(framenum));
02082 int new_lift;
02083 int blocked = Map_chunk::is_blocked(
02084 info.get_3d_height(), tile.tz,
02085 footprint.x, footprint.y, footprint.w, footprint.h,
02086 new_lift, MOVE_ALL_TERRAIN, 1);
02087
02088 if (!blocked && new_lift == tile.tz)
02089 return Usecode_value(1);
02090 else
02091 return Usecode_value(0);
02092 }
02093
02094 USECODE_INTRINSIC(direction_from)
02095 {
02096
02097
02098
02099 Usecode_value u=find_direction(parms[0], parms[1]);
02100 return(u);
02101 }
02102
02103
02104
02105
02106
02107 static int Is_moving_barge_flag
02108 (
02109 int fnum
02110 )
02111 {
02112 if (Game::get_game_type() == BLACK_GATE)
02113 {
02114 return fnum == (int) Obj_flags::on_moving_barge ||
02115 fnum == (int) Obj_flags::in_motion;
02116 }
02117 else
02118 {
02119 return fnum == (int) Obj_flags::si_on_moving_barge ||
02120
02121 fnum == (int) Obj_flags::on_moving_barge ||
02122 fnum == (int) Obj_flags::in_motion;
02123 }
02124 }
02125
02126 USECODE_INTRINSIC(get_item_flag)
02127 {
02128
02129 Game_object *obj = get_item(parms[0]);
02130 if (!obj)
02131 return Usecode_value(0);
02132 int fnum = parms[1].get_int_value();
02133
02134 if (Is_moving_barge_flag(fnum))
02135 {
02136 Barge_object *barge;
02137 if (!gwin->get_moving_barge() || !(barge = Get_barge(obj)))
02138 return Usecode_value(0);
02139 return Usecode_value(barge == gwin->get_moving_barge());
02140 }
02141 else if (fnum == (int) Obj_flags::okay_to_land)
02142 {
02143 Barge_object *barge = Get_barge(obj);
02144 if (!barge)
02145 return Usecode_value(0);
02146 return Usecode_value(barge->okay_to_land());
02147 }
02148 else if (fnum == (int) Obj_flags::cant_die)
02149 {
02150 Monster_info *inf = obj->get_info().get_monster_info();
02151 return Usecode_value(inf != 0 && inf->cant_die());
02152 }
02153
02154
02155 else if (fnum == 0x18 && Game::get_game_type() == BLACK_GATE)
02156 return Usecode_value(1);
02157 else if (fnum == (int) Obj_flags::in_dungeon)
02158 return Usecode_value(obj == gwin->get_main_actor() &&
02159 gwin->is_in_dungeon());
02160 else if (fnum == 0x14)
02161
02162 return Usecode_value(sailor);
02163 Usecode_value u(obj->get_flag(fnum) != 0);
02164 return(u);
02165 }
02166
02167 USECODE_INTRINSIC(set_item_flag)
02168 {
02169
02170 Game_object *obj = get_item(parms[0]);
02171 int flag = parms[1].get_int_value();
02172 if (!obj)
02173 return no_ret;
02174 switch (flag)
02175 {
02176 case Obj_flags::dont_move:
02177 obj->set_flag(flag);
02178
02179 if (obj == gwin->get_main_actor() &&
02180 Game::get_game_type() == SERPENT_ISLE &&
02181 gwin->in_combat())
02182 gwin->toggle_combat();
02183
02184 gwin->set_all_dirty();
02185 break;
02186 case Obj_flags::invisible:
02187 if (as_actor(obj))
02188 {
02189 obj->set_flag(flag);
02190 gwin->add_dirty(obj);
02191 }
02192 break;
02193 case 0x14:
02194 sailor = obj;
02195 default:
02196 obj->set_flag(flag);
02197 if (Is_moving_barge_flag(flag))
02198 {
02199 Barge_object *barge = Get_barge(obj);
02200 if (barge)
02201 gwin->set_moving_barge(barge);
02202 }
02203 break;
02204 }
02205 return(no_ret);
02206 }
02207
02208 USECODE_INTRINSIC(clear_item_flag)
02209 {
02210
02211 Game_object *obj = get_item(parms[0]);
02212 int flag = parms[1].get_int_value();
02213 if (obj)
02214 {
02215 obj->clear_flag(flag);
02216 if (flag == Obj_flags::dont_move)
02217 {
02218 show_pending_text();
02219 gwin->set_all_dirty();
02220 }
02221 else if (Is_moving_barge_flag(flag))
02222 {
02223 Barge_object *barge = Get_barge(obj);
02224 if (barge && barge == gwin->get_moving_barge())
02225 gwin->set_moving_barge(0);
02226 }
02227 else if (flag == 0x14)
02228 sailor = 0;
02229 }
02230 return(no_ret);
02231 }
02232
02233 USECODE_INTRINSIC(set_path_failure)
02234 {
02235
02236
02237
02238 int fun = parms[0].get_int_value(),
02239 eventid = parms[2].get_int_value();
02240 Game_object *item = get_item(parms[1]);
02241 if (path_npc && item)
02242 {
02243 If_else_path_actor_action *action =
02244 path_npc->get_action() ?
02245 path_npc->get_action()->as_usecode_path() : 0;
02246 if (action)
02247 action->set_failure(
02248 new Usecode_actor_action(fun, item, eventid));
02249 }
02250 return no_ret;
02251 }
02252
02253 USECODE_INTRINSIC(fade_palette)
02254 {
02255
02256 int cycles = parms[0].get_int_value();
02257 int inout = parms[2].get_int_value();
02258 if (inout == 0)
02259 show_pending_text();
02260 gwin->get_pal()->fade(cycles, inout);
02261 return(no_ret);
02262 }
02263
02264 USECODE_INTRINSIC(get_party_list2)
02265 {
02266
02267
02268
02269 Usecode_value u(get_party());
02270 return(u);
02271 }
02272
02273 USECODE_INTRINSIC(set_camera)
02274 {
02275
02276 Actor *actor = as_actor(get_item(parms[0]));
02277 if (actor)
02278 gwin->set_camera_actor(actor);
02279 return no_ret;
02280 }
02281
02282 USECODE_INTRINSIC(in_combat)
02283 {
02284
02285 return Usecode_value(gwin->in_combat());
02286 }
02287
02288 USECODE_INTRINSIC(center_view)
02289 {
02290
02291 Game_object *obj = get_item(parms[0]);
02292 if (obj)
02293 {
02294 Tile_coord t = obj->get_tile();
02295 gwin->center_view(t);
02296 activate_cached(t);
02297 }
02298 return no_ret;
02299 }
02300
02301 USECODE_INTRINSIC(get_dead_party)
02302 {
02303
02304 int cnt = partyman->get_dead_count();
02305 Usecode_value ret(cnt, 0);
02306 for (int i = 0; i < cnt; i++)
02307 {
02308 Game_object *body = gwin->get_body(
02309 partyman->get_dead_member(i));
02310
02311 if (body && body->distance(gwin->get_main_actor()) < 50)
02312 {
02313 Usecode_value v(body);
02314 ret.put_elem(i, v);
02315 }
02316 }
02317 return ret;
02318 }
02319
02320 USECODE_INTRINSIC(play_sound_effect)
02321 {
02322 if (num_parms < 1) return(no_ret);
02323
02324 COUT("Sound effect " << parms[0].get_int_value() << " request in usecode");
02325
02326 Audio::get_ptr()->play_sound_effect (parms[0].get_int_value());
02327 return(no_ret);
02328 }
02329
02330 USECODE_INTRINSIC(play_sound_effect2)
02331 {
02332 if (num_parms < 2) return(no_ret);
02333
02334 Game_object *obj = get_item(parms[1]);
02335 int volume = SDL_MIX_MAXVOLUME;
02336 int dir = 0;
02337 if (obj)
02338 {
02339 Tile_coord apos = gwin->get_main_actor()->get_tile();
02340 Tile_coord opos = obj->get_tile();
02341 int dist = apos.distance(opos);
02342 if (dist)
02343 {
02344 volume = (SDL_MIX_MAXVOLUME*64)/(dist*dist);
02345 if (volume < 8)
02346 volume = 8;
02347 else if (volume > SDL_MIX_MAXVOLUME)
02348 volume = SDL_MIX_MAXVOLUME;
02349 dir = Get_direction16(apos.ty - opos.ty,
02350 opos.tx - apos.tx);
02351 }
02352 }
02353 #ifdef DEBUG
02354 cout << "Sound effect(2) " << parms[0].get_int_value() <<
02355 " request in usecode with volume = " << volume
02356 << ", dir = " << dir << endl;
02357 #endif
02358 Audio::get_ptr()->play_sound_effect (parms[0].get_int_value(), volume,
02359 dir);
02360 return(no_ret);
02361 }
02362
02363 USECODE_INTRINSIC(get_npc_id)
02364 {
02365 Actor *actor = as_actor(get_item(parms[0]));
02366 if (!actor) return(no_ret);
02367 return Usecode_value (actor->get_ident());
02368 }
02369
02370 USECODE_INTRINSIC(set_npc_id)
02371 {
02372 Actor *actor = as_actor(get_item(parms[0]));
02373 if (actor) actor->set_ident(parms[1].get_int_value());
02374 return(no_ret);
02375 }
02376
02377
02378 USECODE_INTRINSIC(add_cont_items)
02379 {
02380
02381 return add_cont_items(parms[0], parms[1], parms[2],
02382 parms[3], parms[4], parms[5]);
02383 }
02384
02385
02386 USECODE_INTRINSIC(remove_cont_items)
02387 {
02388
02389 return remove_cont_items(parms[0], parms[1], parms[2],
02390 parms[3], parms[4], parms[5]);
02391 }
02392
02393
02394
02395
02396
02397 USECODE_INTRINSIC(show_npc_face0)
02398 {
02399
02400 show_npc_face(parms[0], parms[1], 0);
02401 return no_ret;
02402 }
02403
02404 USECODE_INTRINSIC(show_npc_face1)
02405 {
02406
02407 show_npc_face(parms[0], parms[1], 1);
02408 return no_ret;
02409 }
02410
02411 USECODE_INTRINSIC(remove_npc_face0)
02412 {
02413 show_pending_text();
02414 conv->remove_slot_face(0);
02415 return no_ret;
02416 }
02417
02418 USECODE_INTRINSIC(remove_npc_face1)
02419 {
02420 show_pending_text();
02421 conv->remove_slot_face(1);
02422 return no_ret;
02423 }
02424
02425 USECODE_INTRINSIC(set_conversation_slot)
02426 {
02427
02428 conv->set_slot(parms[0].get_int_value());
02429 return no_ret;
02430 }
02431
02432 USECODE_INTRINSIC(init_conversation)
02433 {
02434 init_conversation();
02435 return no_ret;
02436 }
02437
02438 USECODE_INTRINSIC(end_conversation)
02439 {
02440 show_pending_text();
02441 conv->init_faces();
02442 gwin->set_all_dirty();
02443 return no_ret;
02444 }
02445
02446 USECODE_INTRINSIC(si_path_run_usecode)
02447 {
02448
02449
02450
02451 int always = parms[5].get_int_value();
02452 path_run_usecode(parms[0], parms[1], parms[4], parms[3], parms[2], 1,
02453 always);
02454 return no_ret;
02455 }
02456
02457 USECODE_INTRINSIC(error_message)
02458 {
02459
02460
02461
02462 for (int i = 0; i < num_parms; i++)
02463 {
02464 if (parms[i].is_int()) std::cout << parms[i].get_int_value() ;
02465 else if (parms[i].is_ptr()) std::cout << parms[i].get_ptr_value();
02466 else if (!parms[i].is_array()) std::cout << parms[i].get_str_value();
02467 else for (int j = 0; j < parms[i].get_array_size(); j++)
02468 {
02469 if (parms[i].get_elem(j).is_int()) std::cout << parms[i].get_elem(j).get_int_value() ;
02470 else if (parms[i].get_elem(j).is_ptr()) std::cout << parms[i].get_elem(j).get_ptr_value();
02471 else if (!parms[i].get_elem(j).is_array()) std::cout << parms[i].get_elem(j).get_str_value();
02472 }
02473 }
02474
02475 std::cout << std::endl;
02476 return no_ret;
02477 }
02478
02479 USECODE_INTRINSIC(set_polymorph)
02480 {
02481
02482
02483 Actor *actor = as_actor(get_item(parms[0]));
02484 if (actor) actor->set_polymorph(parms[1].get_int_value());
02485 return no_ret;
02486 }
02487
02488 USECODE_INTRINSIC(set_new_schedules)
02489 {
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499 Actor *actor = as_actor(get_item(parms[0]));
02500
02501
02502 if (!actor) return no_ret;
02503
02504 int count = parms[1].is_array()?parms[1].get_array_size():1;
02505 Schedule_change *list = new Schedule_change[count];
02506
02507 if (!parms[1].is_array())
02508 {
02509 int time = parms[1].get_int_value();
02510 int sched = parms[2].get_int_value();
02511 int tx = parms[3].get_elem(0).get_int_value();
02512 int ty = parms[3].get_elem(1).get_int_value();
02513 list[0].set(tx, ty, sched, time);
02514 }
02515 else for (int i = 0; i < count; i++)
02516 {
02517 int time = parms[1].get_elem(i).get_int_value();
02518 int sched = parms[2].get_elem(i).get_int_value();
02519 int tx = parms[3].get_elem(i*2).get_int_value();
02520 int ty = parms[3].get_elem(i*2+1).get_int_value();
02521 list[i].set(tx, ty, sched, time);
02522 }
02523
02524 actor->set_schedules(list, count);
02525
02526 return no_ret;
02527 }
02528
02529 USECODE_INTRINSIC(revert_schedule)
02530 {
02531
02532
02533
02534
02535 Actor *actor = as_actor(get_item(parms[0]));
02536 if (actor) gwin->revert_schedules(actor);
02537
02538 return no_ret;
02539 }
02540
02541 USECODE_INTRINSIC(run_schedule)
02542 {
02543
02544
02545
02546 Actor *actor = as_actor(get_item(parms[0]));
02547
02548 if (actor)
02549 {
02550 actor->update_schedule(gclock->get_hour()/3, 7);
02551
02552 }
02553
02554 return no_ret;
02555 }
02556
02557 USECODE_INTRINSIC(modify_schedule)
02558 {
02559
02560
02561 Actor *actor = as_actor(get_item(parms[0]));
02562
02563
02564 if (!actor) return no_ret;
02565
02566 int time = parms[1].get_int_value();
02567 int sched = parms[2].get_int_value();
02568 int tx = parms[3].get_elem(0).get_int_value();
02569 int ty = parms[3].get_elem(1).get_int_value();
02570
02571 actor->set_schedule_time_type(time, sched);
02572 actor->set_schedule_time_location(time, tx, ty);
02573
02574 return no_ret;
02575 }
02576
02577 USECODE_INTRINSIC(get_temperature)
02578 {
02579 Actor *npc = as_actor(get_item(parms[0]));
02580 return Usecode_value(npc ? npc->get_temperature() : 0);
02581 }
02582
02583 USECODE_INTRINSIC(set_temperature)
02584 {
02585
02586 Actor *npc = as_actor(get_item(parms[0]));
02587 if (npc)
02588 npc->set_temperature(parms[1].get_int_value());
02589 return no_ret;
02590 }
02591
02592 #if 0
02593 USECODE_INTRINSIC(add_removed_npc)
02594 {
02595
02596
02597
02598
02599
02600
02601 Actor *actor = as_actor(get_item(parms[0]));
02602
02603
02604 int cx = actor->get_cx();
02605 int cy = actor->get_cx();
02606 int scx = cx / c_chunks_per_schunk;
02607 int scy = cy / c_chunks_per_schunk;
02608 int scx2 = parms[1].get_int_value() / c_tiles_per_schunk;
02609 int scy2 = parms[2].get_int_value() / c_tiles_per_schunk;
02610
02611
02612 if ( (cx == 0xff && scx2) || (cx != 0xff && scx != scx2) ||
02613 (cy == 0xff && scy2) || (cy != 0xff && scy != scy2) )
02614 return (Usecode_value(false));
02615
02616
02617
02618
02619
02620
02621 Rectangle rect = gwin->get_win_tile_rect();
02622
02623 int sx = rect.x;
02624 int ex = rect.x + rect.w;
02625 int sy = rect.y;
02626 int ey = rect.y + rect.h;
02627
02628
02629 int height = actor->get_info().get_3d_height();
02630
02631 int i = 0, nlift = 0;
02632 int tx, ty;
02633
02634
02635 Tile_coord av = gwin->get_main_actor()->get_tile();;
02636
02637 Tile_coord close;
02638 int dist = -1;
02639
02640 cy = sy/c_tiles_per_chunk;
02641 ty = sy%c_tiles_per_chunk;
02642 cout << "1" << endl;
02643 for (i = 0; i < rect.w; i++)
02644 {
02645 cx = (sx+i)/c_tiles_per_chunk;
02646 tx = (sx+i)%c_tiles_per_chunk;
02647
02648 Map_chunk *clist = gmap->get_chunk_safely(cx, cy);
02649 clist->setup_cache();
02650 if (!clist->is_blocked (height, 0, tx, ty, nlift, actor->get_type_flags(), 1))
02651 {
02652 Tile_coord cur(tx+cx*c_tiles_per_chunk, ty+cy*c_tiles_per_chunk, nlift);
02653 if (cur.distance(av) < dist || dist == -1)
02654 {
02655 dist = cur.distance(av);
02656 cout << "(" << cur.tx << ", " << cur.ty << ") " << dist << endl;
02657 close = cur;
02658 }
02659 }
02660 }
02661
02662 cx = ex/c_tiles_per_chunk;
02663 tx = ex%c_tiles_per_chunk;
02664 cout << "2" << endl;
02665 for (i = 0; i < rect.h; i++)
02666 {
02667 cy = (sy+i)/c_tiles_per_chunk;
02668 ty = (sy+i)%c_tiles_per_chunk;
02669
02670 Map_chunk *clist = gmap->get_chunk_safely(cx, cy);
02671 clist->setup_cache();
02672 if (!clist->is_blocked (height, 0, tx, ty, nlift, actor->get_type_flags(), 1))
02673 {
02674 Tile_coord cur(tx+cx*c_tiles_per_chunk, ty+cy*c_tiles_per_chunk, nlift);
02675 if (cur.distance(av) < dist || dist == -1)
02676 {
02677 dist = cur.distance(av);
02678 cout << "(" << cur.tx << ", " << cur.ty << ") " << dist << endl;
02679 close = cur;
02680 }
02681 }
02682 }
02683
02684 cy = ey/c_tiles_per_chunk;
02685 ty = ey%c_tiles_per_chunk;
02686 cout << "3" << endl;
02687 for (i = 0; i < rect.w; i++)
02688 {
02689 cx = (ex-i)/c_tiles_per_chunk;
02690 tx = (ex-i)%c_tiles_per_chunk;
02691
02692 Map_chunk *clist = gmap->get_chunk_safely(cx, cy);
02693 clist->setup_cache();
02694 if (!clist->is_blocked (height, 0, tx, ty, nlift, actor->get_type_flags(), 1))
02695 {
02696 Tile_coord cur(tx+cx*c_tiles_per_chunk, ty+cy*c_tiles_per_chunk, nlift);
02697 if (cur.distance(av) < dist || dist == -1)
02698 {
02699 dist = cur.distance(av);
02700 cout << "(" << cur.tx << ", " << cur.ty << ") " << dist << endl;
02701 close = cur;
02702 }
02703 }
02704 }
02705
02706 cx = sx/c_tiles_per_chunk;
02707 tx = sx%c_tiles_per_chunk;
02708 cout << "4" << endl;
02709 for (i = 0; i < rect.h; i++)
02710 {
02711 cy = (ey-i)/c_tiles_per_chunk;
02712 ty = (ey-i)%c_tiles_per_chunk;
02713
02714 Map_chunk *clist = gmap->get_chunk_safely(cx, cy);
02715 clist->setup_cache();
02716 if (!clist->is_blocked (height, 0, tx, ty, nlift, actor->get_type_flags(), 1))
02717 {
02718 Tile_coord cur(tx+cx*c_tiles_per_chunk, ty+cy*c_tiles_per_chunk, nlift);
02719 if (cur.distance(av) < dist || dist == -1)
02720 {
02721 dist = cur.distance(av);
02722 cout << "(" << cur.tx << ", " << cur.ty << ") " << dist << endl;
02723 close = cur;
02724 }
02725 }
02726 }
02727
02728 if (dist != -1)
02729 {
02730 actor->move(close);
02731 return (Usecode_value(true));
02732 }
02733
02734 return (Usecode_value(false));
02735 }
02736 #endif
02737
02738 USECODE_INTRINSIC(approach_avatar)
02739 {
02740
02741
02742 Actor *actor = as_actor(get_item(parms[0]));
02743 if (!actor || actor->is_dead())
02744 return Usecode_value(0);
02745
02746 if (actor->distance(gwin->get_main_actor()) < 10)
02747 return Usecode_value(1);
02748
02749 if (!actor->approach_another(gwin->get_main_actor(), true))
02750 return Usecode_value(0);
02751 return Usecode_value(1);
02752 }
02753
02754 USECODE_INTRINSIC(set_barge_dir)
02755 {
02756
02757 Game_object *obj = get_item(parms[0]);
02758 int dir = parms[1].get_int_value();
02759 Barge_object *barge = obj ? obj->as_barge() : 0;
02760 if (barge)
02761 barge->face_direction(dir);
02762 return no_ret;
02763 }
02764
02765 USECODE_INTRINSIC(telekenesis)
02766 {
02767
02768 telekenesis_fun = parms[0].get_int_value();
02769 return no_ret;
02770 }
02771
02772 USECODE_INTRINSIC(a_or_an)
02773 {
02774
02775
02776
02777 if (strchr("aeiouyAEIOUY", (parms[0].get_str_value())[0]) == 0)
02778 return (Usecode_value("a"));
02779 else
02780 return (Usecode_value("an"));
02781
02782 }
02783
02784 USECODE_INTRINSIC(remove_from_area)
02785 {
02786
02787 int shnum = parms[0].get_int_value(), frnum = parms[1].get_int_value();
02788 int fromx = parms[2].get_elem(0).get_int_value(),
02789 fromy = parms[2].get_elem(1).get_int_value(),
02790 tox = parms[3].get_elem(0).get_int_value(),
02791 toy = parms[3].get_elem(1).get_int_value();
02792 Rectangle area(fromx, fromy, tox - fromx + 1, toy - fromy + 1);
02793 if (area.w <= 0 || area.h <= 0)
02794 return no_ret;
02795 Game_object_vector vec;
02796 Map_chunk::find_in_area(vec, area, shnum, frnum);
02797
02798 for (Game_object_vector::iterator it = vec.begin(); it != vec.end();
02799 it++)
02800 {
02801 Game_object *obj = *it;
02802 gwin->add_dirty(obj);
02803 obj->remove_this(0);
02804 }
02805 return no_ret;
02806 }
02807
02808 USECODE_INTRINSIC(infravision)
02809 {
02810
02811 Actor *npc = as_actor(get_item(parms[0]));
02812 if (npc && npc->is_in_party())
02813 {
02814 if (parms[1].get_int_value())
02815 {
02816 cheat.set_infravision(true);
02817 gwin->get_pal()->set(0);
02818 }
02819 else
02820 {
02821 cheat.set_infravision(false);
02822 gclock->set_palette();
02823 }
02824 }
02825 return no_ret;
02826 }
02827
02828
02829 USECODE_INTRINSIC(add_to_keyring)
02830 {
02831 getKeyring()->addkey(parms[0].get_int_value());
02832
02833 return no_ret;
02834 }
02835
02836
02837
02838
02839 USECODE_INTRINSIC(is_on_keyring)
02840 {
02841 if (getKeyring()->checkkey(parms[0].get_int_value()))
02842 return Usecode_value(true);
02843 else
02844 return Usecode_value(false);
02845 }
02846
02847 USECODE_INTRINSIC(save_pos)
02848 {
02849
02850 Game_object *item = get_item(parms[0]);
02851 if (item)
02852 saved_pos = item->get_tile();
02853 return no_ret;
02854 }
02855
02856 USECODE_INTRINSIC(teleport_to_saved_pos)
02857 {
02858
02859 Actor *npc = as_actor(get_item(parms[0]));
02860 if (npc == gwin->get_main_actor())
02861 {
02862 if (saved_pos.tx < 0 || saved_pos.tx >= c_num_tiles)
02863
02864 saved_pos = Tile_coord(719, 2608, 1);
02865 gwin->teleport_party(saved_pos);
02866 }
02867 return no_ret;
02868 }
02869
02870 USECODE_INTRINSIC(get_item_usability)
02871 {
02872
02873 Game_object *obj = get_item(parms[0]);
02874 if (!obj || !obj->is_dragable())
02875 return Usecode_value(0);
02876 else
02877 return Usecode_value(1);
02878 }
02879
02880 USECODE_INTRINSIC(get_skin_colour)
02881 {
02882
02883 Main_actor *av = gwin->get_main_actor();
02884 return Usecode_value(av->get_skin_color());
02885 }
02886
02887
02888
02889
02890
02891
02892 USECODE_INTRINSIC(printf)
02893 {
02894 Usecode_value ret("");
02895 const char *fmt = parms[0].get_elem0().get_str_value();
02896 int count;
02897 cout << endl;
02898 if (!fmt || (count = parms[0].get_array_size()) <= 1)
02899 {
02900 parms[0].print(cout);
02901 return ret;
02902 }
02903 int i = 1;
02904 while (*fmt)
02905 {
02906 const char *spec = strchr(fmt, '%');
02907 if (!spec)
02908 spec = fmt + std::strlen(fmt);
02909 cout.write(fmt, spec - fmt);
02910 if (*spec == '%')
02911 {
02912 if (spec[1] == 's')
02913 {
02914 Usecode_value p = i < count ? parms[0][i]
02915 : Usecode_value(0);
02916 if (p.get_type() == Usecode_value::int_type)
02917 cout << p.get_int_value();
02918 else
02919 p.print(cout);
02920 spec += 2;
02921 }
02922 else
02923 {
02924 cout << '%';
02925 spec++;
02926 }
02927 }
02928 fmt = spec;
02929 }
02930 return ret;
02931 }
02932