From a1e062c8b27fcf2f65d5a21fc85fbcc80abfa86f Mon Sep 17 00:00:00 2001 From: fusion32 Date: Tue, 3 Jun 2025 02:08:15 -0300 Subject: more spells --- reference/game.c | 538 ------------------------------------------------------- src/magic.cc | 262 ++++++++++++++++++++++++++- src/stubs.hh | 1 + 3 files changed, 255 insertions(+), 546 deletions(-) diff --git a/reference/game.c b/reference/game.c index 138c00e..65ac6f5 100644 --- a/reference/game.c +++ b/reference/game.c @@ -20852,544 +20852,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return; } -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void MagicRope(void) - -{ - bool bVar1; - undefined4 *puVar2; - TCreature *in_stack_00000004; - int in_stack_00000008; - int in_stack_0000000c; - int iVar3; - undefined4 uVar4; - int local_58; - int x; - int y; - int z; - Object local_3c [4]; - Object local_2c [4]; - ulong local_1c; - Object Obj; - - if (in_stack_00000004 == (TCreature *)0x0) { - error(&DAT_080fb4a0); - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0xffffffff; - } - else { - local_2c[0].ObjectID = (in_stack_00000004->CrObject).ObjectID; - local_1c = local_2c[0].ObjectID; - // try { // try from 08082d0e to 08082e18 has its CatchHandler @ 08082e30 - GetObjectCoordinates(local_2c,&local_58,&x,&y); - uVar4 = 0x32; - iVar3 = x; - bVar1 = CoordinateFlag(); - if (bVar1) { - CheckMana(in_stack_00000004,in_stack_00000008,in_stack_0000000c,1000); - local_2c[0].ObjectID = NONE.ObjectID; - GetMapContainer((int)local_3c,local_58,x + 1); - z = local_1c; - Move(0,(Object *)&z,local_3c,-1,false,local_2c); - GraphicalEffect(); - return; - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4,iVar3,y,uVar4); - *puVar2 = 1; - } - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void MagicClimbing(void) - -{ - bool bVar1; - int iVar2; - undefined4 *puVar3; - int dz; - int iVar4; - TCreature *in_stack_00000004; - int in_stack_00000008; - int in_stack_0000000c; - char *in_stack_00000010; - char *Text; - int *x_00; - int *y_00; - int *z_00; - int *local_70; - int dy; - int dx; - int x; - int y; - int z; - Object local_4c [4]; - Object local_3c [4]; - ulong local_2c; - Object Obj; - - if (in_stack_00000004 == (TCreature *)0x0) { - Text = &DAT_080fb520; - } - else { - if (in_stack_00000010 != (char *)0x0) { - local_3c[0].ObjectID = (in_stack_00000004->CrObject).ObjectID; - x_00 = &dx; - z_00 = &y; - y_00 = &x; - local_2c = local_3c[0].ObjectID; - // try { // try from 08082e99 to 08083153 has its CatchHandler @ 08083174 - GetObjectCoordinates(local_3c,x_00,y_00,z_00); - iVar4 = y; - dy = dx; - local_70 = (int *)x; - iVar2 = in_stack_00000004->Direction; - if (iVar2 == 1) { - dy = dx + 1; - } - else if (iVar2 < 2) { - if (iVar2 == 0) { - local_70 = (int *)(x + -1); - } - } - else if (iVar2 == 2) { - local_70 = (int *)(x + 1); - } - else if (iVar2 == 3) { - dy = dx + -1; - } - if (y < 1) { -LAB_08082f00: - if (y < 0xf) { - y_00 = (int *)0xffffffff; - x_00 = (int *)&DAT_080fdfc1; - iVar2 = stricmp(in_stack_00000010,"down",-1); - if (iVar2 == 0) { - z_00 = (int *)0x0; - x_00 = local_70; - y_00 = (int *)y; - bVar1 = CoordinateFlag(); - if (!bVar1) { - z_00 = (int *)0x20; - x_00 = local_70; - y_00 = (int *)y; - bVar1 = CoordinateFlag(); - if (!bVar1) { - z_00 = (int *)(y + 1); - x_00 = (int *)dy; - y_00 = local_70; - iVar2 = (*in_stack_00000004->_vptr_TCreature[3])(); - if ((char)iVar2 != '\0') { - iVar4 = iVar4 + 1; - goto LAB_08082f09; - } - } - } - goto LAB_08082fb4; - } - } -LAB_08082f09: - if (y != iVar4) { - CheckMana(in_stack_00000004,in_stack_00000008,in_stack_0000000c,1000); - local_3c[0].ObjectID = NONE.ObjectID; - GetMapContainer((int)local_4c,dy,(int)local_70); - z = local_2c; - Move(0,(Object *)&z,local_4c,-1,false,local_3c); - GraphicalEffect(); - return; - } - } - else { - y_00 = (int *)0xffffffff; - x_00 = (int *)&DAT_080fdfbe; - iVar2 = stricmp(in_stack_00000010,"up",-1); - if (iVar2 != 0) goto LAB_08082f00; - z_00 = (int *)0x0; - y_00 = (int *)(y + -1); - x_00 = (int *)x; - bVar1 = CoordinateFlag(); - if (!bVar1) { - z_00 = (int *)0x20; - y_00 = (int *)(y + -1); - bVar1 = CoordinateFlag(); - x_00 = (int *)x; - if (!bVar1) { - z_00 = (int *)(y + -1); - x_00 = (int *)dy; - y_00 = local_70; - iVar2 = (*in_stack_00000004->_vptr_TCreature[3])(); - if ((char)iVar2 != '\0') { - iVar4 = iVar4 + -1; - goto LAB_08082f00; - } - } - } - } -LAB_08082fb4: - puVar3 = (undefined4 *)__cxa_allocate_exception(4,x_00,y_00,z_00); - *puVar3 = 1; - goto LAB_08082fc6; - } - Text = &DAT_080fb4e0; - } - error(Text); - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; -LAB_08082fc6: - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); -} - - - -void MagicClimbing(TCreature *cr,char *Direction) - -{ - bool bVar1; - undefined4 *puVar2; - char *Text; - - if (cr == (TCreature *)0x0) { - Text = &DAT_080fb520; - } - else if (Direction == (char *)0x0) { - Text = &DAT_080fb4e0; - } - else { - if (cr->Type == PLAYER) { - // try { // try from 080831cd to 08083233 has its CatchHandler @ 08083246 - bVar1 = CheckRight(cr->ID,LEVITATE); - if (bVar1) { - MagicClimbing(); - } - return; - } - Text = "MagicClimbing: Zauberspruch kann nur von Spielern angewendet werden.\n"; - } - error(Text); - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); -} - - - -void CreateThing(TCreature *cr,char *Param1,char *Param2) - -{ - bool bVar1; - bool bVar2; - int iVar3; - TConnection *Connection; - undefined4 *puVar4; - char *pcVar5; - int local_60; - int Count; - Object Con; - Object local_4c [4]; - ObjectType local_3c [4]; - ObjectType local_2c; - ObjectType Type; - - if (cr == (TCreature *)0x0) { - pcVar5 = &DAT_080fb720; -LAB_08083596: - error(pcVar5); - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); - } - if (Param1 == (char *)0x0) { - pcVar5 = &DAT_080fb6e0; - goto LAB_08083596; - } - if (cr->Type != PLAYER) { - pcVar5 = "CreateThing: Zauberspruch kann nur von Spielern angewendet werden.\n"; - goto LAB_08083596; - } - // try { // try from 080832a7 to 080835c4 has its CatchHandler @ 080835d7 - bVar1 = CheckRight(cr->ID,CREATE_OBJECTS); - if (!bVar1) { - return; - } - ObjectType::setTypeID(&local_2c,0); - local_60 = 1; - iVar3 = __strtol_internal(Param1,0,10,0); - if (iVar3 == 0) { - GetObjectTypeByName((char *)local_4c,SUB41(Param1,0)); - } - else { - iVar3 = __strtol_internal(Param1,0,10,0); - bVar1 = false; - ObjectType::setTypeID(local_3c,99); - if ((local_3c[0].TypeID < iVar3) && (bVar2 = ObjectTypeExists(iVar3), bVar2)) { - bVar1 = true; - } - if (bVar1) { - ObjectType::setTypeID((ObjectType *)&Count,iVar3); - ObjectType::setTypeID(&local_2c,Count); - ObjectType::setTypeID((ObjectType *)local_4c,local_2c.TypeID); - } - bVar1 = ObjectType::getFlag(&local_2c,UNMOVE); - if (!bVar1) goto LAB_08083369; - ObjectType::setTypeID((ObjectType *)local_4c,0); - } - ObjectType::setTypeID(&local_2c,local_4c[0].ObjectID); - ObjectType::setTypeID((ObjectType *)&Count,local_2c.TypeID); -LAB_08083369: - ObjectType::setTypeID((ObjectType *)&Count,0); - if (local_2c.TypeID == Count) { - Connection = cr->Connection; - pcVar5 = "There is no such takeable object."; - } - else { - if (Param2 != (char *)0x0) { - local_60 = __strtol_internal(Param2,0,10,0); - } - if (local_60 - 1U < 100) { - bVar1 = ObjectType::getFlag(&local_2c,TAKE); - if ((bVar1) || (local_60 == 1)) { - local_4c[0].ObjectID = (cr->CrObject).ObjectID; - GetMapContainer((Object *)&Count); - bVar1 = ObjectType::getFlag(&local_2c,CUMULATIVE); - if (bVar1) { - ObjectType::setTypeID(local_3c,local_2c.TypeID); - CreateAtCreature((ulong)local_4c,(ObjectType *)cr->ID,(ulong)local_3c); - } - else { - iVar3 = 0; - if (0 < local_60) { - do { - ObjectType::setTypeID(local_3c,local_2c.TypeID); - CreateAtCreature((ulong)local_4c,(ObjectType *)cr->ID,(ulong)local_3c); - iVar3 = iVar3 + 1; - } while (iVar3 < local_60); - } - } - local_4c[0].ObjectID = Count; - GraphicalEffect(local_4c,0xf); - return; - } - Connection = cr->Connection; - pcVar5 = "You may only create one untakeable object."; - } - else { - Connection = cr->Connection; - pcVar5 = "You may only create 1 to 100 objects."; - } - } - SendMessage(Connection,0x17,pcVar5); - return; -} - - - -void CreateMoney(TCreature *cr,char *Param) - -{ - bool bVar1; - int iVar2; - undefined4 *puVar3; - char *Text; - Object local_4c [4]; - ulong local_3c [4]; - Object local_2c; - Object Con; - - if (cr == (TCreature *)0x0) { - Text = &DAT_080fb840; - } - else if (Param == (char *)0x0) { - Text = &DAT_080fb800; - } - else { - if (cr->Type == PLAYER) { - // try { // try from 08083634 to 08083816 has its CatchHandler @ 08083830 - bVar1 = CheckRight(cr->ID,CREATE_MONEY); - if (bVar1) { - iVar2 = __strtol_internal(Param,0,10,0); - if (iVar2 - 1U < 1000000) { - local_3c[0] = (cr->CrObject).ObjectID; - GetMapContainer(&local_2c); - if (0 < iVar2 / 10000) { - GetSpecialObject((SPECIALMEANING)local_4c); - CreateAtCreature((ulong)local_3c,(ObjectType *)cr->ID,(ulong)local_4c); - } - if (0 < (iVar2 % 10000) / 100) { - GetSpecialObject((SPECIALMEANING)local_3c); - CreateAtCreature((ulong)local_4c,(ObjectType *)cr->ID,(ulong)local_3c); - } - if (0 < iVar2 % 100) { - GetSpecialObject((SPECIALMEANING)local_3c); - CreateAtCreature((ulong)local_4c,(ObjectType *)cr->ID,(ulong)local_3c); - } - local_4c[0].ObjectID = local_2c.ObjectID; - GraphicalEffect(local_4c,0xf); - } - else { - SendMessage(cr->Connection,0x17,"You may only create 1 to 1,000,000 gold."); - } - } - return; - } - Text = "CreateMoney: Zauberspruch kann nur von Spieler angewendet werden.\n"; - } - error(Text); - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void CreateFood(void) - -{ - int iVar1; - int iVar2; - ObjectType *this; - undefined4 *puVar3; - int i; - int iVar4; - TCreature *in_stack_00000004; - int in_stack_00000008; - int in_stack_0000000c; - uchar Number; - int max; - ObjectType local_3c [4]; - ObjectType local_2c; - ObjectType Type; - - if (in_stack_00000004 == (TCreature *)0x0) { - error(&DAT_080fb880); - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); - } - // try { // try from 08083883 to 08083a64 has its CatchHandler @ 08083a65 - CheckMana(in_stack_00000004,in_stack_00000008,in_stack_0000000c,1000); - iVar1 = rand(); - iVar1 = iVar1 % 2 + 1; - iVar4 = 0; - if (0 < iVar1) { - do { - ObjectType::setTypeID(&local_2c,0); - iVar2 = rand(); - switch(iVar2 % 7) { - case 0: - GetNewObjectType((uchar)&max,0x86); - ObjectType::setTypeID(&local_2c,max); - this = local_3c; - goto LAB_0808392c; - case 1: - goto LAB_080839b1; - case 2: - Number = 0x88; - break; - case 3: -LAB_080839b1: - Number = 0x82; - break; - case 4: - goto LAB_08083a09; - case 5: -LAB_08083a09: - Number = 0x83; - break; - case 6: - Number = 0x86; - break; - default: - goto switchD_080838ee_default; - } - GetNewObjectType((uchar)local_3c,Number); - ObjectType::setTypeID(&local_2c,local_3c[0].TypeID); - this = (ObjectType *)&max; -LAB_0808392c: - ObjectType::setTypeID(this,local_2c.TypeID); -switchD_080838ee_default: - ObjectType::setTypeID(local_3c,local_2c.TypeID); - CreateAtCreature((ulong)&max,(ObjectType *)in_stack_00000004->ID,(ulong)local_3c); - iVar4 = iVar4 + 1; - } while (iVar4 < iVar1); - } - max = (in_stack_00000004->CrObject).ObjectID; - GraphicalEffect((Object *)&max,0xf); - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void CreateArrows(void) - -{ - undefined4 *puVar1; - TCreature *in_stack_00000004; - int in_stack_00000008; - int in_stack_0000000c; - undefined4 in_stack_00000010; - Object *this; - Object local_4c [4]; - Object local_3c [4]; - ObjectType local_2c; - ObjectType Type; - - if (in_stack_00000004 == (TCreature *)0x0) { - error(&DAT_080fb900); -LAB_08083bee: - puVar1 = (undefined4 *)__cxa_allocate_exception(4); - *puVar1 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar1,&RESULT::typeinfo,0); - } - // try { // try from 08083ab6 to 08083c23 has its CatchHandler @ 08083c26 - CheckMana(in_stack_00000004,in_stack_00000008,in_stack_0000000c,1000); - ObjectType::setTypeID(&local_2c,0); - switch(in_stack_00000010) { - case 0: - GetNewObjectType((uchar)local_4c,'^'); - ObjectType::setTypeID(&local_2c,local_4c[0].ObjectID); - this = local_3c; - goto LAB_08083b18; - case 1: - break; - case 2: - break; - case 3: - break; - case 4: - break; - default: - error(&DAT_080fb8c0); - goto LAB_08083bee; - } - GetNewObjectType((uchar)local_3c,'^'); - ObjectType::setTypeID(&local_2c,local_3c[0].ObjectID); - this = local_4c; -LAB_08083b18: - ObjectType::setTypeID((ObjectType *)this,local_2c.TypeID); - ObjectType::setTypeID((ObjectType *)local_3c,local_2c.TypeID); - CreateAtCreature((ulong)local_4c,(ObjectType *)in_stack_00000004->ID,(ulong)local_3c); - local_4c[0].ObjectID = (in_stack_00000004->CrObject).ObjectID; - GraphicalEffect(local_4c,0xd); - return; -} - - - void SummonCreature(TCreature *cr,int Mana,int Race,bool God) { diff --git a/src/magic.cc b/src/magic.cc index 170a8d8..dc91695 100644 --- a/src/magic.cc +++ b/src/magic.cc @@ -1356,13 +1356,7 @@ void Teleport(TCreature *Actor, char *Param){ int DestX = Actor->posx; int DestY = Actor->posy; int DestZ = Actor->posz; - // TODO(fusion): The `HouseID` parameter of `SearchFreeField` can be 0xFFFF - // as a wildcard to any house. This is probably only used for these special - // commands and we should have a `HOUSEID_ANY` constant defined somewhere. - // If it is something else, the function will try to find a free field with - // the same house id. I'm not sure why we use it with marks but I think we - // should only use 0xFFFF here. - uint16 HouseID = 0xFFFF; + uint16 HouseID = HOUSEID_ANY; int MDGoStrength = Actor->Skills[SKILL_GO_STRENGTH]->MDAct; if(stricmp(Param, "up") == 0){ @@ -1420,7 +1414,8 @@ void Teleport(TCreature *Actor, char *Param){ DestX = ParamX; DestY = ParamY; DestZ = ParamZ; - // TODO(fusion): Not sure why we do this here. + // TODO(fusion): Not sure why we do this here. Maybe `TELEPORT_TO_MARK` + // was also assigned to a couple of non GM characters? HouseID = GetHouseID(DestX, DestY, DestZ); }else{ SendMessage(Actor->Connection, TALK_FAILURE_MESSAGE, "There is no mark of this name."); @@ -1547,6 +1542,257 @@ void TeleportPlayerToMe(TCreature *Actor, const char *Name){ GraphicalEffect(DestX, DestY, DestZ, EFFECT_TELEPORT); } +void MagicRope(TCreature *Actor, int ManaPoints, int SoulPoints){ + if(Actor == NULL){ + error("MagicRope: Ungültige Kreatur übergeben.\n"); + throw ERROR; + } + + int OrigX = Actor->posx; + int OrigY = Actor->posy; + int OrigZ = Actor->posz; + if(!CoordinateFlag(OrigX, OrigY, OrigZ, ROPESPOT)){ + throw NOTACCESSIBLE; + } + + CheckMana(Actor, ManaPoints, SoulPoints, 1000); + + Object Dest = GetMapContainer(OrigX, OrigY + 1, OrigZ - 1); + Move(0, Actor->CrObject, Dest, -1, false, NONE); + GraphicalEffect(OrigX, OrigY, OrigZ, EFFECT_TELEPORT); +} + +void MagicClimbing(TCreature *Actor, int ManaPoints, int SoulPoints, const char *Param){ + if(Actor == NULL){ + error("MagicClimbing: Ungültige Kreatur übergeben.\n"); + throw ERROR; + } + + if(Param == NULL){ + error("MagicClimbing: Ungültige Richtung übergeben.\n"); + throw ERROR; + } + + int OrigX = Actor->posx; + int OrigY = Actor->posy; + int OrigZ = Actor->posz; + + // TODO(fusion): This is probably an inlined function `TCreature::GetForwardPosition`. + int DestX = OrigX; + int DestY = OrigY; + int DestZ = OrigZ; + switch(Actor->Direction){ + case DIRECTION_NORTH: DestY -= 1; break; + case DIRECTION_EAST: DestX += 1; break; + case DIRECTION_SOUTH: DestY += 1; break; + case DIRECTION_WEST: DestX -= 1; break; + } + + if(stricmp(Param, "up") == 0){ + if(OrigZ > 0 && !CoordinateFlag(OrigX, OrigY, OrigZ - 1, BANK) + && !CoordinateFlag(OrigX, OrigY, OrigZ - 1, UNPASS) + && Actor->MovePossible(DestX, DestY, OrigZ - 1, true, true)){ + DestZ -= 1; + } + }else if(stricmp(Param, "down") == 0){ + if(OrigZ < 15 && !CoordinateFlag(DestX, DestY, OrigZ, BANK) + && !CoordinateFlag(DestX, DestY, OrigZ, UNPASS) + && Actor->MovePossible(DestX, DestY, OrigZ + 1, true, true)){ + DestZ += 1; + } + } + + if(DestZ == OrigZ){ + throw NOTACCESSIBLE; + } + + CheckMana(Actor, ManaPoints, SoulPoints, 1000); + + Object Dest = GetMapContainer(DestX, DestY, DestZ); + Move(0, Actor->CrObject, Dest, -1, false, NONE); + GraphicalEffect(OrigX, OrigY, OrigZ, EFFECT_TELEPORT); +} + +void MagicClimbing(TCreature *Actor, const char *Param){ + // TODO(fusion): I think this is a version used by GM characters. + if(Actor == NULL){ + error("MagicClimbing: Ungültige Kreatur übergeben.\n"); + throw ERROR; + } + + if(Param == NULL){ + error("MagicClimbing: Ungültige Richtung übergeben.\n"); + throw ERROR; + } + + if(Actor->Type != PLAYER){ + error("MagicClimbing: Zauberspruch kann nur von Spielern angewendet werden.\n"); + throw ERROR; + } + + if(CheckRight(Actor->ID, LEVITATE)){ + MagicClimbing(Actor, 0, 0, Param); + } +} + +void CreateThing(TCreature *Actor, const char *Param1, const char *Param2){ + if(Actor == NULL){ + error("CreateThing: Ungültige Kreatur übergeben.\n"); + throw ERROR; + } + + if(Param1 == NULL){ + error("CreateThing: Ungültiger Parameter \"Param1\".\n"); + throw ERROR; + } + + if(Actor->Type != PLAYER){ + error("CreateThing: Zauberspruch kann nur von Spielern angewendet werden.\n"); + throw ERROR; + } + + if(!CheckRight(Actor->ID, CREATE_OBJECTS)){ + return; + } + + int TypeID = atoi(Param1); + if(TypeID != 0){ + if(TypeID < 100 || !ObjectTypeExists(TypeID) + || ObjectType(TypeID).getFlag(UNMOVE)){ + TypeID = 0; + } + }else{ + TypeID = GetObjectTypeByName(Param1, true).TypeID; + } + + if(TypeID == 0){ + SendMessage(Actor->Connection, TALK_FAILURE_MESSAGE, + "There is no such takeable object."); + return; + } + + int Count = (Param2 != NULL ? atoi(Param2) : 1); + if(Count < 1 || Count > 100){ + SendMessage(Actor->Connection, TALK_FAILURE_MESSAGE, + "You may only create 1 to 100 objects."); + return; + } + + ObjectType ObjType(TypeID); + if(!ObjType.getFlag(TAKE) && Count > 0){ + SendMessage(Actor->Connection, TALK_FAILURE_MESSAGE, + "You may only create one untakeable object."); + return; + } + + if(!ObjType.getFlag(CUMULATIVE)){ + for(int i = 0; i < Count; i += 1){ + CreateAtCreature(Actor->ID, ObjType, 1); + } + }else{ + CreateAtCreature(Actor->ID, ObjType, Count); + } + + GraphicalEffect(Actor->posx, Actor->posy, Actor->posz, EFFECT_MAGIC_GREEN); +} + +void CreateMoney(TCreature *Actor, const char *Param){ + if(Actor == NULL){ + error("CreateMoney: Ungültige Kreatur übergeben.\n"); + throw ERROR; + } + + if(Param == NULL){ + error("CreateMoney: Ungültiger Parameter \"Param1\".\n"); + throw ERROR; + } + + if(Actor->Type != PLAYER){ + error("CreateMoney: Zauberspruch kann nur von Spieler angewendet werden.\n"); + throw ERROR; + } + + if(!CheckRight(Actor->ID, CREATE_MONEY)){ + return; + } + + int Amount = atoi(Param); + if(Amount < 1 || Amount > 1000000){ + SendMessage(Actor->Connection, TALK_FAILURE_MESSAGE, + "You may only create 1 to 1,000,000 gold."); + } + + int Crystal = (Amount / 10000); + int Platinum = (Amount % 10000) / 100; + int Gold = (Amount % 10000) % 100; + + if(Crystal > 0){ + CreateAtCreature(Actor->ID, GetSpecialObject(MONEY_TENTHOUSAND), Crystal); + } + + if(Platinum > 0){ + CreateAtCreature(Actor->ID, GetSpecialObject(MONEY_HUNDRED), Platinum); + } + + if(Gold > 0){ + CreateAtCreature(Actor->ID, GetSpecialObject(MONEY_ONE), Gold); + } + + GraphicalEffect(Actor->posx, Actor->posy, Actor->posz, EFFECT_MAGIC_GREEN); +} + +void CreateFood(TCreature *Actor, int ManaPoints, int SoulPoints){ + if(Actor == NULL){ + error("CreateFood: Ungültige Kreatur übergeben.\n"); + throw ERROR; + } + + CheckMana(Actor, ManaPoints, SoulPoints, 1000); + + int Count = (rand() % 2) + 1; + for(int i = 0; i < Count; i += 1){ + uint8 Group, Number; + switch(rand() % 7){ + case 0: Group = 134; Number = 0; break; + case 1: Group = 130; Number = 2; break; + case 2: Group = 136; Number = 0; break; + case 3: Group = 130; Number = 13; break; + case 4: Group = 131; Number = 1; break; + case 5: Group = 131; Number = 9; break; + case 6: Group = 134; Number = 1; break; + default: ASSERT(!"unreachable"); break; + } + CreateAtCreature(Actor->ID, GetNewObjectType(Group, Number), 1); + } + + GraphicalEffect(Actor->posx, Actor->posy, Actor->posz, EFFECT_MAGIC_GREEN); +} + +void CreateArrows(TCreature *Actor, int ManaPoints, int SoulPoints, int ArrowType, int Count){ + if(Actor == NULL){ + error("CreateArrows: Ungültige Kreatur übergeben.\n"); + throw ERROR; + } + + CheckMana(Actor, ManaPoints, SoulPoints, 1000); + + uint8 Number; + switch(ArrowType){ + case 0: Number = 1; break; + case 1: Number = 2; break; + case 2: Number = 3; break; + case 3: Number = 0; break; + case 4: Number = 4; break; + default:{ + error("CreateArrows: Ungültiger Pfeiltyp %d.\n", ArrowType); + throw ERROR; + } + } + + CreateAtCreature(Actor->ID, GetNewObjectType(94, Number), Count); + GraphicalEffect(Actor->posx, Actor->posy, Actor->posz, EFFECT_MAGIC_BLUE); +} + // Magic Init Functions // ============================================================================= static void InitCircles(void){ diff --git a/src/stubs.hh b/src/stubs.hh index 7b10798..4157c61 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -27,6 +27,7 @@ extern void CircleShapeSpell(TCreature *Actor, int DestX, int DestY, int DestZ, extern void CleanHouseField(int x, int y, int z); extern int ComputeDamage(TCreature *Creature, int SpellNr, int Damage, int Variation); extern int CountInventoryObjects(uint32 CreatureID, ObjectType Type, uint32 Value); +extern Object CreateAtCreature(uint32 CreatureID, ObjectType Type, uint32 Value); extern void CreateField(int x, int y, int z, int FieldType, uint32 Owner, bool Peaceful); extern void CreateMonster(int Race, int x, int y, int z, int Home, uint32 Master, bool ShowEffect); extern void CreatePlayerList(bool Online); -- cgit v1.2.3