Initial commit

This commit is contained in:
2025-02-07 00:23:09 +01:00
commit 22fd76a153
2841 changed files with 107275 additions and 0 deletions

View File

@@ -0,0 +1,231 @@
static var old_target;
var setTarget(var target)
{
old_target = target;
}
var getTarget()
{
UI_error_message("Old target is " + old_target);
return old_target;
}
//Chain bolt replaces create gold.
void chainLightning object#()()
// void chainLightning shape#(var target, var shots_left)()
//var chainLightning(var target, var shots_left)
{
var target_count = 9;
var target = item; //getTarget();
enum chainLightning_events
{
CHAIN_BOLT = 1,
CHAIN_BOLT_LOOP = 2
};
if (event == CHAIN_BOLT_LOOP)
{
var num_shots = UI_get_npc_id(CHAIN_BOLT); //npc -132
UI_error_message("Chain bolt loop called. Num shots left is " + num_shots);
if (num_shots > 9)
{
script target after 10 ticks
{
call chainLightning, CHAIN_BOLT;
}
target_count -= 1;
UI_error_message("target count is " + target_count);
}
UI_set_npc_id(CHAIN_BOLT, num_shots - 1); //lower "count"
}
if (event == CHAIN_BOLT)
{
const int SHAPE_LIGHTNING = 807; //807
//target chosen should be the one chosen by the initial casting of the spell
var target = item; //getTarget();
var current_target_shape = UI_get_item_shape(target);
UI_error_message("Current target shape in event CHAIN_BOLT is " + current_target_shape);
var current_target_npc_num = UI_get_npc_number(target);
var current_target_npc_name = UI_get_npc_name(target);
var current_target_object = UI_get_npc_object(target);
UI_error_message("chainLightning called, event CHAIN_BOLT. Target 1 is " + current_target_object);
if (target)
UI_error_message("There is an initial target");
else
UI_error_message("No initial target");
//var avatar_level = getExpLevel(AVATAR);
var num_shots = UI_get_npc_id(CHAIN_BOLT); //npc -132
//select a new target:
//first get all npcs in a 15 tile range of target, then add them to an array. Discards any GOOD aligned targets. Select a random target from that array:
var dist = 20; //tiles which we want to check
var npc_list = target->find_nearby(-359, dist, 0x08);
var npc_list_num = UI_get_array_size(npc_list);
var target_list = [];
var npc_alignment;
UI_error_message("NPC list initially is " + npc_list_num);
var count = 0;
//take npc list and take out party members, put all valid targets in new array
for (npc in npc_list)
{
npc_alignment = UI_get_alignment(npc);
if (npc_alignment == GOOD)
continue;
else
{
UI_error_message("NPC is not GOOD aligned, adding to target list.");
target_list << npc;
count+= 1;
}
}
//randomly select target from npc list:
var target_list_size = UI_get_array_size([target_list]);
UI_error_message("target_list_size array has " + target_list_size + " elements");
var rand = UI_get_random(target_list_size);
UI_error_message("random number for array is " + rand);
var new_target = target_list[rand];
while (target == new_target && count < 10)
{
UI_error_message("Target is the same, re-rolling..");
new_target = target_list[rand];
count += 1;
if (count == 9)
new_target = target_list[2];
}
var new_target_object = UI_get_npc_object(new_target);
UI_error_message("random target is shape " + UI_get_item_shape(new_target) + " and new target object is " + new_target_object);
if (new_target)
UI_error_message("new target should be selected");
//attack the target:
// target->set_to_attack(new_target, SHAPE_LIGHTNING);
// if (UI_set_to_attack(target, new_target, SHAPE_LIGHTNING))
// UI_error_message("Target 1 attacks target 2 successfully");
// else
// UI_error_message("attack failed");
var direction = UI_find_direction(target, new_target);
UI_error_message("direction from target 1 to target 2 is " + direction);
//UI_fire_projectile(target, direction, SHAPE_LIGHTNING, 1, SHAPE_LIGHTNING, SHAPE_LIGHTNING);
UI_set_to_attack(target, new_target, SHAPE_LIGHTNING);
//subtract shots left
//shots_left -= 1;
//set old target
//setTarget(target);
//script target to run chain lightning again, choosing another target
if (target)
{
script new_target after 15 ticks
{
//chainLightning(target, shots_left);
call chainLightning, CHAIN_BOLT_LOOP;
}
}
else
UI_error_message("No more targets.");
}
}
//SPELL////////////////////////////////////////////////////////////////////////////////////////////////
void spellChainBolt object# (0x678)()
{
//var num_shots = getExpLevel(AVATAR); //times the chain lightning will attack different people
if (event == DOUBLECLICK)
{
var target = UI_click_on_item();
var target_shape = target->get_item_shape();
var dir = direction_from(target);
const int SHAPE_LIGHTNING = 807; //807
var dist = 15;
//var target_list = [];
//var num_targets;
//var new_target;
//var npc_alignment;
halt_scheduled();
item_say("@Ort Grav@");
if (inMagicStorm())
{
UI_set_to_attack(AVATAR, target, SHAPE_LIGHTNING);
script AVATAR
{ nohalt; face dir;
actor frame raise_1h; actor frame cast_up;
sfx 65; actor frame cast_out;
actor frame strike_2h; actor frame strike_2h;
attack; actor frame standing;
}
//get random number for "shots left". Adding 2 so there is at least 3 shots to be fired
var shots_left = UI_get_random(6) + 2;
//call the chain lightning script
target->chainLightning();
var num_shots = UI_get_npc_id(CHAIN_BOLT);
UI_set_npc_id(CHAIN_BOLT, 10); //npc -132
UI_error_message("Shots are initially " + num_shots);
// call chainLightning, CHAIN_BOLT_LOOP;
}
else
{
script item
{ nohalt; face dir;
actor frame raise_1h; actor frame cast_up;
actor frame cast_out; actor frame strike_2h;
call spellFails;
}
}
}
}

View File

@@ -0,0 +1,242 @@
void spellEnchantEffect object#() ()
{
var normal_missiles = [SHAPE_ARROWS, SHAPE_BOLTS];
var magic_missiles = [SHAPE_MAGIC_ARROWS, SHAPE_MAGIC_BOLTS];
for (missile in normal_missiles with index)
if (missile == get_item_shape())
set_item_shape(magic_missiles[index]);
}
void spellEnchant object#(0x651) ()
{
var normal_missiles = [SHAPE_ARROWS, SHAPE_BOLTS];
var magic_missiles = [SHAPE_MAGIC_ARROWS, SHAPE_MAGIC_BOLTS];
var BP = UI_count_objects(AVATAR, SHAPE_REAGENT, QUALITY_ANY, FRAME_BLACK_PEARL);
var NS = UI_count_objects(AVATAR, SHAPE_REAGENT, QUALITY_ANY, FRAME_NIGHTSHADE);
var SA = UI_count_objects(AVATAR, SHAPE_REAGENT, QUALITY_ANY, FRAME_SULFUR_ASH);
var BM = UI_count_objects(AVATAR, SHAPE_REAGENT, QUALITY_ANY, FRAME_BLOOD_MOSS);
var MR = UI_count_objects(AVATAR, SHAPE_REAGENT, QUALITY_ANY, FRAME_MANDRAKE_ROOT);
var SS = UI_count_objects(AVATAR, SHAPE_REAGENT, QUALITY_ANY, FRAME_SPIDER_SILK);
var GL = UI_count_objects(AVATAR, SHAPE_REAGENT, QUALITY_ANY, FRAME_GARLIC);
var Avatar_Level = getExpLevel(AVATAR);
if (event == DOUBLECLICK)
{
halt_scheduled();
var target = UI_click_on_item();
var target_shape = target->get_item_shape();
var dir = direction_from(target);
item_say("@Ort Ylem@");
if (target_shape == SHAPE_YEW_STAFF)
{
AVATAR.say("Which spell do you want to enchant it with?");
var spell_options = ["none"];
if (hasSpell(FIRE_BLAST))
add("Fire Blast");
if (hasSpell(DEATH_BOLT))
add("Death Bolt");
if (hasSpell(POISON))
add("Poison");
if (hasSpell(LIGHTNING))
add("Lightning");
converse(spell_options)
{
case "Poison": //BP, BM, NS lvl 3
if (BP >= 10 && BM >= 10 && NS >= 10)
{
if (Avatar_Level >= 3)
{
//set yew staff to enchanted staff (change type!)
UI_set_item_shape(target, SHAPE_YEW_STAFF_POISON);
//give it 10 charges
UI_set_item_quality(target, 10);
//remove regs:
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_BLOOD_MOSS);
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_BLACK_PEARL);
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_NIGHTSHADE);
script item
{ nohalt; face dir;
sfx 67; actor frame reach_1h;
actor frame raise_1h; actor frame strike_1h;
}
return;
}
else
{
AVATAR->spellFails();
avatarBark("@I can't cast that spell yet.@");
return;
}
}
else
{
AVATAR->spellFails();
avatarBark("Requires 10 of each Poison reagent.");
return;
}
case "Fire Blast":
if (BP >= 10 && SA >= 10)
{
if (Avatar_Level >= 2)
{
//set yew staff to enchanted staff (change type!)
UI_set_item_shape(target, SHAPE_YEW_STAFF_FIREBOLT);
//give it 10 charges
UI_set_item_quality(target, 10);
script item
{ nohalt; face dir;
sfx 67; actor frame reach_1h;
actor frame raise_1h; actor frame strike_1h;
}
//remove regs:
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_SULFUR_ASH);
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_BLACK_PEARL);
return;
}
else
{
AVATAR->spellFails();
avatarBark("@I can't cast that spell yet.@");
return;
}
}
else
{
AVATAR->spellFails();
avatarBark("Requires 10 of each Fire Bolt reagent.");
return;
}
case "Death Bolt":
if (BP >= 10 && NS >= 10 && SA >= 10)
{
if (Avatar_Level >= 7)
{
//set yew staff to enchanted staff (change type!)
UI_set_item_shape(target, SHAPE_YEW_STAFF_DEATHBOLT);
//give it 10 charges
UI_set_item_quality(target, 10);
script item
{ nohalt; face dir;
sfx 67; actor frame reach_1h;
actor frame raise_1h; actor frame strike_1h;
}
//remove regs:
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_SULFUR_ASH);
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_NIGHTSHADE);
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_BLACK_PEARL);
return;
}
else
{
AVATAR->spellFails();
avatarBark("@I can't cast that spell yet.@");
return;
}
}
else
{
AVATAR->spellFails();
avatarBark("Requires 10 of each Death Bolt reagent.");
return;
}
case "Lightning": //BP, MR, SA
if (BP >= 10 && SA >= 10 && MR >=10)
{
if (Avatar_Level >= 4)
{
//set yew staff to enchanted staff (change type!)
UI_set_item_shape(target, SHAPE_YEW_STAFF_LIGHTNING);
//give it 10 charges
UI_set_item_quality(target, 10);
script item
{ nohalt; face dir;
sfx 67; actor frame reach_1h;
actor frame raise_1h; actor frame strike_1h;
}
//remove regs:
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_SULFUR_ASH);
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_BLACK_PEARL);
UI_remove_party_items(10, SHAPE_REAGENT, QUALITY_ANY, FRAME_MANDRAKE_ROOT);
return;
}
else
{
AVATAR->spellFails();
avatarBark("@I can't cast that spell yet.@");
return;
}
}
else
{
AVATAR->spellFails();
avatarBark("Requires 10 of each Lightning reagent.");
return;
}
case "none":
return;
}
}
else if (inMagicStorm() && (target_shape in normal_missiles))
{
script item
{ nohalt; face dir;
sfx 67; actor frame reach_1h;
actor frame raise_1h; actor frame strike_1h;}
script target after 4 ticks
{ nohalt; call spellEnchantEffect;}
}
else
{
script item
{ nohalt; face dir;
actor frame reach_1h; actor frame raise_1h;
actor frame strike_1h; call spellFails;
}
}
}
}

View File

@@ -0,0 +1,36 @@
void spellHelp_Override object#(0x645) ()
{
if (event == DOUBLECLICK)
{
var exp = UI_get_npc_prop(AVATAR, EXPERIENCE);
var ten_pct = exp / 10; //gets 10 percent of current exp to dock
var pos = [0x03A7, 0x0432, 0x0, 0x0];
item_say("@Kal Lor@");
if (inMagicStorm())
{
script item
{ nohalt; sfx 67;
actor frame cast_up; actor frame cast_out;
actor frame ready; wait 4;
}
PARTY->move_object(pos);
//dock avatar EXP per original? Cannot find correct amount, docking 10% instead
//UI_set_npc_prop(AVATAR, EXPERIENCE, ten_pct *-2); //DISABLED FOR NOW! (to avoid duplicate training points)
//subtract karma instead (for now?)
subtractKarma(10);
}
else
{
script item
{ nohalt;
actor frame reach_1h; actor frame raise_1h;
actor frame strike_1h; call spellFails;
}
}
}
}

View File

@@ -0,0 +1,153 @@
void spellPickpocket object#(0x669) ()
{
var frame = UI_get_item_frame(item);
var quality = UI_get_item_quality(item);
var level = getExpLevel(AVATAR);
var BM = UI_count_objects(PARTY, SHAPE_REAGENT, QUALITY_ANY, FRAME_BLOOD_MOSS);
var NS = UI_count_objects(PARTY, SHAPE_REAGENT, QUALITY_ANY, FRAME_NIGHTSHADE);
var SS = UI_count_objects(PARTY, SHAPE_REAGENT, QUALITY_ANY, FRAME_SPIDER_SILK);
var AvatarMana = UI_get_npc_prop(AVATAR, MANA);
var stuff;
var counter = 1;
var avatar_pos = UI_get_object_position(AVATAR);
var target_contents;
var stealable_items_count = 0;
var stealable_items;
var cant_steal_items = [807, 731, 857, 856, 902, 1118, 281, 288];
var spots = [BG_WEAPON_HAND, BG_OFF_HAND, BG_BACKPACK, BG_CLOAK, BG_AMULET, BG_HEAD, BG_GLOVES,
BG_RIGHT_RING, BG_LEFT_RING, BG_QUIVER, BG_BELT, BG_TORSO, BG_FEET,
BG_LEGS, BG_BACK_SHIELD, BG_BACK_2H];
if (event == DOUBLECLICK)
{
//check for proper level, mana, reagents
if ((level >= 5) && (BM > 0) && (NS > 0) && (SS > 0) && (AvatarMana >=5))
{
//remove regs and mana points
UI_remove_party_items(1, SHAPE_REAGENT, QUALITY_ANY, FRAME_BLOOD_MOSS);
UI_remove_party_items(1, SHAPE_REAGENT, QUALITY_ANY, FRAME_NIGHTSHADE);
UI_remove_party_items(1, SHAPE_REAGENT, QUALITY_ANY, FRAME_SPIDER_SILK);
UI_set_npc_prop(AVATAR, MANA, -5);
//close all windows
UI_close_gumps();
//get target
var target = UI_click_on_item();
UI_error_message("Target is " + target);
//get array of target contents:
if (UI_is_npc(target))
{
var dir = direction_from(target);
target_contents = UI_get_cont_items(target, SHAPE_ANY, QUALITY_ANY, FRAME_ANY);
var count = UI_count_objects(target);
//TODO: discern between wearable items and backpack items
//array to put stealable items in - stuff in pouches, non magic stuff
var object;
for (object in target_contents)
{
count = count + 1;
}
UI_error_message("Target has " + count + " objects in their inventory");
//pick random item in inventory to steal:
var rand = UI_get_random(count);
//to avoid infinite loop, counter will go up to 20 then give Avatar random amount of stolen gold
var counter = 0;
var invalid_item = true;
while (invalid_item && counter < 21)
{
invalid_item = false;
//determine if item selected to steal is being worn/held
for (spot in spots)
{
UI_error_message("Spot is : " + spot);
var item_to_take = UI_get_item_shape(target_contents[rand]);
UI_error_message("Item is : " + item_to_take);
if (UI_is_readied(target, spot, item_to_take, FRAME_ANY))
{
//item found readied, re-roll
rand = UI_get_random(count);
UI_error_message("Reroll - carrying item found in spot " + spot + " Rand is now: " + rand);
invalid_item = true;
break;
}
}
counter += 1;
}
//no items OR counter was too high
if (count < 1 || counter == 21)
{
rand = UI_get_random(50);
UI_error_message("no items or counter is over 20. Stealing gold instead. Counter is: " + counter);
giveGold(rand);
}
else
{
//transfer item to Avatar
//UI_error_message("Counter is " + counter + " . Item stolen is: " + item_to_take + ".");
UI_set_last_created(target_contents[rand]);
UI_give_last_created(AVATAR);
}
//steal successful, karma loss
subtractKarma(5);
//play sprite effects
UI_obj_sprite_effect(AVATAR, 21, 0, 0, 0, 0, 0, -1); //purple
UI_obj_sprite_effect(target, 13, 0, 0, 0, 0, 0, -1); //green
script AVATAR
{
nohalt; face dir;
say"@Por Ylem@";
actor frame reach_1h; actor frame raise_1h;
actor frame strike_1h; sfx 66;
}
//TODO - chance to call the guards?
}
else //targeted something other than an npc
{
AVATAR->spellFails();
}
}
else
UI_flash_mouse(1);
}
}

View File

@@ -0,0 +1,59 @@
/*
*
* Copyright (C) 2006 The Exult Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
* This header file overrides the spellbook's spells (most of them, anyway)
* to use the new versions. I preferred to do it this way for four reasons:
* (1) There is a clean algorythm by which NPC spells are cast;
* (2) It allows me to override specific spells and leave others;
* (3) I can add new NPC-only spells without removing existing spells.
* (4) It is easier to add NPC-specific spells which only one NPC
* can cast (although I haven't made any such spells yet).
*
* Presently, I haven't overriden Help (except for Multimap support), Recall
* and Armageddon -- I don't think that they are appropriate for NPCs, so I
* left them alone. I _have_ overriden Mark, but only so that is won't be
* possible to use it while inside the Shrine of the Codex.
* All other spells are overriden so that the Avatar and the NPCs play by the
* same rules.
*
* Author: Marzo Junior
* Last Modified: 2006-02-27
*/
//spellAwaken_Override object#(0x640) () {spellAwaken(UI_click_on_item());}
//spellWeather_Override object#(0x641) () {spellWeather();}
//spellDouse_Override object#(0x642) () {spellDouse(UI_click_on_item());}
//spellFireworks_Override object#(0x643) () {spellFireworks();}
//spellGlimmer_Override object#(0x644) () {spellGlimmer();}
spellHelp_Override object#(0x645) ()
{
if (event == DOUBLECLICK)
//If we came here from a doubleclick, forward to original:
spellHelp_Override.original();
else if (event == SCRIPTED)
{
//We got here from a Usecode script, so we override it
//for multi-map support:
var pos = [0x03A7, 0x0432, 0x0, 0x0];
PARTY->move_object(pos);
}
}
extern void spellUnlockMagic_Override object#(0x667) () {spellUnlockMagic(UI_click_on_item());}

View File

@@ -0,0 +1,75 @@
void spellUnlockMagic object#(0x667) () //667 //65f is SLEEP!
{
// Regular Doors
// Same numbers as BG doors plus brass doors
const int SHAPE_DOOR_H1 = 270;
const int SHAPE_DOOR_V1 = 376;
const int SHAPE_DOOR_H2 = 432;
const int SHAPE_DOOR_V2 = 433;
// Secret 'Wall' Doors
const int SHAPE_SECRET_WALL_V = 828;
const int SHAPE_SECRET_WALL_H = 845;
const int SHAPE_LOCKED_CHEST = 522;
const int FRAME_MAGIC_LOCKED_CHEST_H = 2;
const int FRAME_MAGIC_LOCKED_CHEST_V = 3;
const int SHAPE_CHEST = 800;
const int FRAME_CHEST_H = 0;
const int SHAPE_MAGIC_LOCKED_CHEST = 1187;
if (event == DOUBLECLICK)
{
var target = UI_click_on_item();
var target_shape = UI_get_item_shape(target);
var target_frame = UI_get_item_frame(target);
var dir = direction_from(target);
halt_scheduled();
var unlockables = [SHAPE_DOOR_HORIZONTAL, SHAPE_DOOR_VERTICAL, SHAPE_DOOR2_HORIZONTAL, SHAPE_DOOR2_VERTICAL, SHAPE_LOCKED_CHEST, SHAPE_MAGIC_LOCKED_CHEST];
item_say("@Ex Por@");
UI_error_message("Casting unlock magic");
if (inMagicStorm())
{
if (target_shape == SHAPE_MAGIC_LOCKED_CHEST)
{
UI_error_message("Magic chest targeted");
// Set to unlocked chest shape first.
UI_set_item_shape(target, SHAPE_CHEST);
// Set the frame as well, since shape-changes don't reset the frame to 0.
UI_set_item_frame(target, FRAME_CHEST_H);
}
else
UI_error_message("target is NOT magic locked chest");
if (target_shape in unlockables || target_frame in unlockables)
{
if (((target_frame + 1) % 4) == 0)
{
script item
{ nohalt; face dir;
actor frame reach_1h; actor frame raise_1h;
actor frame strike_1h; sfx 66;}
script target after 6 ticks
{ nohalt; frame target_frame - 3;}
return;
}
}
}
else
UI_error_message("Avatar in Magic Storm");
script item
{ nohalt; face dir;
actor frame reach_1h; actor frame raise_1h;
actor frame strike_1h; call spellFails;}
}
}