aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-14 04:47:08 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-14 04:47:08 -0300
commit33464579f6b8b079597617593d2bb733e982db8f (patch)
treeb5da873ddd7d9cd382a4adc321594fdd68fac9bb
parent15b40c7915fca14e537534ae9ba03f3add965943 (diff)
downloadgame-33464579f6b8b079597617593d2bb733e982db8f.tar.gz
game-33464579f6b8b079597617593d2bb733e982db8f.zip
impl `Look` and `Talk`...
-rw-r--r--reference/game.c1127
-rw-r--r--src/info.hh1
-rw-r--r--src/operate.cc645
-rw-r--r--src/stubs.hh3
4 files changed, 649 insertions, 1127 deletions
diff --git a/reference/game.c b/reference/game.c
index 9a9762d..186295c 100644
--- a/reference/game.c
+++ b/reference/game.c
@@ -18375,1133 +18375,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority
return;
}
-void Look(ulong CreatureID,Object *Obj)
-
-{
- TSkill *this;
- bool bVar1;
- byte bVar2;
- ushort HouseID;
- int Profession;
- TPlayer *pTVar3;
- TPlayer *this_00;
- ulong uVar4;
- int iVar5;
- uint uVar6;
- ulong uVar7;
- undefined4 *puVar8;
- TCreature *cr;
- TConnection *Connection;
- char *pcVar9;
- char *pcVar10;
- Object *Buffer;
- int local_5bc;
- int c;
- bool Yourself;
- TPlayer *pl;
- int x;
- int y;
- int z;
- int MagicLevel;
- char Pronoun [4];
- char s2 [500];
- char local_39c [4];
- char s [500];
- Object local_19c;
- char HelpProfession [30];
- char Membership [200];
- char local_ac [4];
- char Vocation [50];
- char local_6c [4];
- char Player [50];
- Object local_2c [7];
-
- // try { // try from 0809494b to 08095fb2 has its CatchHandler @ 08095fc0
- pTVar3 = GetPlayer(CreatureID);
- if (pTVar3 == (TPlayer *)0x0) {
- pcVar9 = "Look: Kreatur existiert nicht.\n";
-LAB_08095f84:
- error(pcVar9);
- puVar8 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar8 = 0xffffffff;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar8,&RESULT::typeinfo,0);
- }
- bVar1 = Object::exists(Obj);
- if (!bVar1) {
- pcVar9 = "Look: Objekt existiert nicht.\n";
- goto LAB_08095f84;
- }
- Object::getObjectType(local_2c);
- if (local_2c[0].ObjectID == 99) {
- local_2c[0] = (Object)Obj->ObjectID;
- this_00 = (TPlayer *)GetCreature(local_2c);
- if (this_00 == (TPlayer *)0x0) {
- Object::getObjectType(local_2c);
- error("Look: Object %d hat keine Kreatur!\n",local_2c[0].ObjectID);
- return;
- }
- if ((this_00->super_TCreature).Type == PLAYER) {
- uVar4 = Object::getCreatureID(Obj);
- bVar1 = CreatureID == uVar4;
- if (bVar1) {
- builtin_strncpy(local_6c,"your",4);
- builtin_strncpy(Player,"self",5);
- }
- else {
- this = (this_00->super_TCreature).super_TSkillBase.Skills[0];
- if (this == (TSkill *)0x0) {
- iVar5 = 1;
- }
- else {
- iVar5 = TSkill::Get(this);
- }
- snprintf(local_6c,0x32,"%s (Level %d)",(this_00->super_TCreature).Name,iVar5);
- }
- if ((this_00->super_TCreature).Sex == 2) {
- MagicLevel = 0x656853;
- }
- else {
- MagicLevel = CONCAT13(MagicLevel._3_1_,0x6548);
- }
- bVar2 = TPlayer::GetActiveProfession(this_00);
- uVar6 = (uint)bVar2;
- if (bVar1) {
- if (uVar6 == 0) {
- builtin_strncpy(Vocation,"have no vocation",0x11);
- builtin_strncpy(local_ac,"You ",4);
- goto LAB_08094ad9;
- }
- Buffer = &local_19c;
- GetProfessionName((char *)Buffer,uVar6,true,false);
- pcVar9 = "You are %s";
- }
- else {
- if (uVar6 != 0) {
- GetProfessionName((char *)&local_19c,uVar6,true,false);
- snprintf(local_ac,0x32,"%s is %s",&MagicLevel,&local_19c);
- goto LAB_08094ad9;
- }
- pcVar9 = "%s has no vocation";
- Buffer = (Object *)&MagicLevel;
- }
- snprintf(local_ac,0x32,pcVar9,Buffer);
-LAB_08094ad9:
- if (this_00->Guild[0] == '\0') {
- stack0xfffffe84 = stack0xfffffe84 & 0xffffff00;
- }
- else {
- if (bVar1) {
- stack0xfffffe84 = 0x20756f59;
- }
- else {
- snprintf(HelpProfession + 0x1c,200,"%s is ",&MagicLevel);
- }
- if (this_00->Rank[0] == '\0') {
- pcVar9 = "a member";
- }
- else {
- pcVar9 = this_00->Rank;
- }
- strcat(HelpProfession + 0x1c,pcVar9);
- strcat(HelpProfession + 0x1c," of the ");
- strcat(HelpProfession + 0x1c,this_00->Guild);
- if (this_00->Title[0] != '\0') {
- strcat(HelpProfession + 0x1c," (");
- strcat(HelpProfession + 0x1c,this_00->Title);
- strcat(HelpProfession + 0x1c,")");
- }
- }
- if (HelpProfession[0x1c] != '\0') {
- SendMessage((pTVar3->super_TCreature).Connection,0x16,"You see %s. %s. %s.",local_6c
- ,local_ac,HelpProfession + 0x1c);
- return;
- }
- SendMessage((pTVar3->super_TCreature).Connection,0x16,"You see %s. %s.",local_6c,
- local_ac);
- return;
- }
- pcVar9 = (this_00->super_TCreature).Name;
- Connection = (pTVar3->super_TCreature).Connection;
- pcVar10 = "You see %s.";
- goto LAB_080949d4;
- }
- builtin_strncpy(s,"see ",5);
- builtin_strncpy(local_39c,"You ",4);
- local_2c[0] = (Object)Obj->ObjectID;
- pcVar9 = GetName(local_2c);
- strcat(local_39c,pcVar9);
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,LEVELDOOR);
- if (bVar1) {
- uVar4 = Object::getAttribute(Obj,DOORLEVEL);
- sprintf(Pronoun," for level %lu",uVar4);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER);
- if (bVar1) {
- Object::getObjectType(local_2c);
- uVar4 = ObjectType::getAttribute((ObjectType *)local_2c,CAPACITY);
- sprintf(Pronoun," (Vol:%lu)",uVar4);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,WEAPON);
- if (bVar1) {
- Object::getObjectType(local_2c);
- uVar4 = ObjectType::getAttribute((ObjectType *)local_2c,WEAPONDEFENDVALUE);
- Object::getObjectType(local_2c);
- uVar7 = ObjectType::getAttribute((ObjectType *)local_2c,WEAPONATTACKVALUE);
- sprintf(Pronoun," (Atk:%lu Def:%lu)",uVar7,uVar4);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,THROW);
- if (bVar1) {
- Object::getObjectType(local_2c);
- uVar4 = ObjectType::getAttribute((ObjectType *)local_2c,THROWDEFENDVALUE);
- Object::getObjectType(local_2c);
- uVar7 = ObjectType::getAttribute((ObjectType *)local_2c,THROWATTACKVALUE);
- sprintf(Pronoun," (Atk:%lu Def:%lu)",uVar7,uVar4);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,SHIELD);
- if (bVar1) {
- Object::getObjectType(local_2c);
- uVar4 = ObjectType::getAttribute((ObjectType *)local_2c,SHIELDDEFENDVALUE);
- sprintf(Pronoun," (Def:%lu)",uVar4);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,ARMOR);
- if (bVar1) {
- Object::getObjectType(local_2c);
- uVar4 = ObjectType::getAttribute((ObjectType *)local_2c,ARMORVALUE);
- sprintf(Pronoun," (Arm:%lu)",uVar4);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,KEY);
- if (bVar1) {
- uVar4 = Object::getAttribute(Obj,KEYNUMBER);
- sprintf(Pronoun," (Key:%04ld)",uVar4);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,KEYDOOR);
- if ((bVar1) && (bVar1 = CheckRight((pTVar3->super_TCreature).ID,SHOW_KEYHOLE_NUMBERS), bVar1)) {
- uVar4 = Object::getAttribute(Obj,KEYHOLENUMBER);
- sprintf(Pronoun," (Door:%04ld)",uVar4);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,SHOWDETAIL);
- if (bVar1) {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,WEAROUT);
- if (bVar1) {
- Object::getObjectType(local_2c);
- uVar4 = ObjectType::getAttribute((ObjectType *)local_2c,TOTALUSES);
- if (uVar4 < 2) goto LAB_08095af9;
- uVar4 = Object::getAttribute(Obj,REMAININGUSES);
- pcVar9 = "";
- if (uVar4 != 1) {
- pcVar9 = "s";
- }
- uVar4 = Object::getAttribute(Obj,REMAININGUSES);
- sprintf(Pronoun," that has %ld charge%s left",uVar4,pcVar9);
- pcVar9 = Pronoun;
- }
- else {
-LAB_08095af9:
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,EXPIRE);
- if (!bVar1) {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,EXPIRESTOP);
- if (!bVar1) {
- Object::getObjectType(local_2c);
- error("Look: Objekt %d hat Flag SHOWDETAIL, aber weder WEAROUT noch EXPIRE.\n",
- local_2c[0].ObjectID);
- goto LAB_08094f1f;
- }
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,EXPIRE);
- if (bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- uVar4 = CronInfo(local_2c,false);
- }
- else {
- uVar4 = Object::getAttribute(Obj,SAVEDEXPIRETIME);
- }
- uVar6 = (uVar4 + 0x3b) / 0x3c;
- if (uVar6 == 0) {
- pcVar9 = " that is brand-new";
- }
- else {
- pcVar9 = "";
- if (uVar6 != 1) {
- pcVar9 = "s";
- }
- sprintf(Pronoun," that has energy for %d minute%s left",uVar6,pcVar9);
- pcVar9 = Pronoun;
- }
- }
- strcat(local_39c,pcVar9);
- }
-LAB_08094f1f:
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,RESTRICTLEVEL);
- if (bVar1) {
-LAB_08094f69:
- strcat(local_39c,".\nIt can only be wielded by ");
- Pronoun = (char [4])((uint)Pronoun & 0xffffff00);
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,RESTRICTPROFESSION);
- if (bVar1) {
- iVar5 = 5;
- local_5bc = 0;
- do {
- Object::getObjectType(local_2c);
- uVar4 = ObjectType::getAttribute((ObjectType *)local_2c,PROFESSIONS);
- if (iVar5 == 5) {
- uVar6 = uVar4 & 1;
- }
- else {
- uVar6 = 1 << ((byte)iVar5 & 0x1f) & uVar4;
- }
- if (uVar6 != 0) {
- if (local_5bc == 0) {
- stack0xfffffe84 = stack0xfffffe84 & 0xffffff00;
- }
- if (local_5bc == 1) {
- sprintf(HelpProfession + 0x1c," and %s",Pronoun);
- }
- if (1 < local_5bc) {
- sprintf(HelpProfession + 0x1c,", %s",Pronoun);
- }
- switch(iVar5) {
- case 1:
- builtin_strncpy(Pronoun,"knig",4);
- break;
- case 2:
- builtin_strncpy(Pronoun,"pala",4);
- break;
- case 3:
- builtin_strncpy(Pronoun,"sorc",4);
- break;
- case 4:
- builtin_strncpy(Pronoun,"drui",4);
- break;
- case 5:
- builtin_strncpy(Pronoun,"play",4);
- }
- strcat(Pronoun,HelpProfession + 0x1c);
- local_5bc = local_5bc + 1;
- }
- iVar5 = iVar5 + -1;
- } while (0 < iVar5);
- }
- else {
- builtin_strncpy(Pronoun,"play",4);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,RESTRICTLEVEL);
- if (bVar1) {
- Object::getObjectType(local_2c);
- uVar4 = ObjectType::getAttribute((ObjectType *)local_2c,MINIMUMLEVEL);
- sprintf(HelpProfession + 0x1c," of level %ld or higher",uVar4);
- strcat(Pronoun,HelpProfession + 0x1c);
- }
- strcat(local_39c,Pronoun);
- }
- else {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,RESTRICTPROFESSION);
- if (bVar1) goto LAB_08094f69;
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,RUNE);
- if (bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- GetMagicItemDescription(local_2c,Pronoun,&z);
- if (z != 0) {
- sprintf((char *)&local_19c," for magic level %d",z);
- strcat(local_39c,(char *)&local_19c);
- }
- strcat(local_39c,". It\'s an \"");
- strcat(local_39c,Pronoun);
- strcat(local_39c,"\"-spell");
- uVar4 = Object::getAttribute(Obj,CHARGES);
- sprintf(Pronoun," (%ldx)",uVar4);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,BED);
- if ((bVar1) && (uVar4 = Object::getAttribute(Obj,TEXTSTRING), uVar4 != 0)) {
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- pcVar9 = GetDynamicString(uVar4);
- sprintf(Pronoun,". %s is sleeping there",pcVar9);
- strcat(local_39c,Pronoun);
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,NAMEDOOR);
- if (bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- GetObjectCoordinates(local_2c,(int *)&pl,&x,&y);
- HouseID = GetHouseID((int)pl,x,y);
- if (HouseID == 0) {
- error(&DAT_080ffd20,pl,x,y);
- }
- else {
- pcVar9 = GetHouseName(HouseID);
- sprintf(Pronoun,". It belongs to house \'%s\'",pcVar9);
- strcat(local_39c,Pronoun);
- pcVar9 = GetHouseOwner(HouseID);
- if ((pcVar9 == (char *)0x0) || (*pcVar9 == '\0')) {
- builtin_strncpy(Pronoun,". No",4);
- }
- else {
- sprintf(Pronoun,". %s owns this house",pcVar9);
- }
- strcat(local_39c,Pronoun);
- }
- }
- strcat(local_39c,".");
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,LIQUIDCONTAINER);
- if ((bVar1) && (uVar4 = Object::getAttribute(Obj,CONTAINERLIQUIDTYPE), uVar4 == 0)) {
-LAB_08095675:
- strcat(local_39c," It is empty.");
- }
- else {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,LIQUIDPOOL);
- if ((bVar1) && (uVar4 = Object::getAttribute(Obj,POOLLIQUIDTYPE), uVar4 == 0))
- goto LAB_08095675;
- }
- if (CreatureID == 0) {
-LAB_080951b8:
- Object::getObjectType((Object *)(HelpProfession + 0xc));
- bVar1 = ObjectType::getFlag((ObjectType *)(HelpProfession + 0xc),TAKE);
- if (bVar1) {
- HelpProfession._12_4_ = Obj->ObjectID;
- iVar5 = GetWeight((Object *)(HelpProfession + 0xc),-1);
- if (0 < iVar5) {
- local_19c = (Object)Obj->ObjectID;
- iVar5 = GetCompleteWeight(&local_19c);
- Object::getObjectType(&local_19c);
- bVar1 = ObjectType::getFlag((ObjectType *)&local_19c,CUMULATIVE);
- if ((bVar1) && (uVar4 = Object::getAttribute(Obj,AMOUNT), 1 < uVar4)) {
- Object::getObjectType(&local_19c);
- pcVar9 = ObjectType::getName((ObjectType *)&local_19c);
- bVar1 = IsCountable(pcVar9);
- if (!bVar1) goto LAB_0809559b;
- pcVar9 = "\nThey weigh %d.%02d oz.";
- }
- else {
-LAB_0809559b:
- pcVar9 = "\nIt weighs %d.%02d oz.";
- }
- sprintf(Pronoun,pcVar9,iVar5 / 100,iVar5 % 100);
- strcat(local_39c,Pronoun);
- }
- }
- HelpProfession._12_4_ = Obj->ObjectID;
- pcVar9 = GetInfo((Object *)(HelpProfession + 0xc));
- if (pcVar9 != (char *)0x0) {
- local_19c = (Object)Obj->ObjectID;
- pcVar9 = GetInfo(&local_19c);
- snprintf(Pronoun,500,"\n%s.",pcVar9);
- strcat(local_39c,Pronoun);
- }
- }
- else {
- local_2c[0] = (Object)Obj->ObjectID;
- bVar1 = ObjectInRange(CreatureID,local_2c,1);
- if (bVar1) goto LAB_080951b8;
- }
- Object::getObjectType((Object *)(HelpProfession + 0xc));
- bVar1 = ObjectType::getFlag((ObjectType *)(HelpProfession + 0xc),TEXT);
- if (bVar1) {
- Object::getObjectType((Object *)(HelpProfession + 0xc));
- uVar4 = ObjectType::getAttribute((ObjectType *)(HelpProfession + 0xc),FONTSIZE);
- if ((ushort)uVar4 == 0) {
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- if (uVar4 == 0) goto LAB_080952a3;
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- pcVar9 = GetDynamicString(uVar4);
- pcVar10 = "\n%s.";
-LAB_0809540b:
- snprintf(Pronoun,500,pcVar10,pcVar9);
- }
- else if ((ushort)uVar4 < 2) {
-LAB_080952a3:
- Pronoun = (char [4])((uint)Pronoun & 0xffffff00);
- }
- else {
- uVar7 = Object::getAttribute(Obj,TEXTSTRING);
- if (uVar7 == 0) {
- builtin_strncpy(Pronoun,"\nNot",4);
- }
- else {
- if (CreatureID != 0) {
- HelpProfession._12_4_ = Obj->ObjectID;
- bVar1 = ObjectInRange(CreatureID,(Object *)(HelpProfession + 0xc),uVar4 & 0xffff
- );
- if (!bVar1) {
- builtin_strncpy(Pronoun,"\nYou",4);
- goto LAB_080952aa;
- }
- }
- uVar4 = Object::getAttribute(Obj,EDITOR);
- if (uVar4 == 0) {
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- pcVar9 = GetDynamicString(uVar4);
- pcVar10 = "\nYou read: %s";
- goto LAB_0809540b;
- }
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- pcVar9 = GetDynamicString(uVar4);
- uVar4 = Object::getAttribute(Obj,EDITOR);
- pcVar10 = GetDynamicString(uVar4);
- snprintf(Pronoun,500,"\n%s has written: %s",pcVar10,pcVar9);
- }
- }
-LAB_080952aa:
- strcat(local_39c,Pronoun);
- }
- pcVar9 = local_39c;
- Connection = (pTVar3->super_TCreature).Connection;
- pcVar10 = "%s";
-LAB_080949d4:
- SendMessage(Connection,0x16,pcVar10,pcVar9);
- return;
-}
-
-
-
-void Talk(ulong CreatureID,int Mode,char *Addressee,char *Text,bool CheckSpamming)
-
-{
- bool bVar1;
- ulong ID;
- TPlayer *this;
- size_t sVar2;
- ulong uVar3;
- TCreature *pTVar4;
- TPlayer *pTVar5;
- int iVar6;
- TChannel *pTVar7;
- ulong *puVar8;
- TListener *pTVar9;
- TStatement *pTVar10;
- ulong uVar11;
- TConnection *pTVar12;
- undefined4 *puVar13;
- int dx;
- uint uVar14;
- char *pcVar15;
- TCreature *cr_1;
- uint uVar16;
- TPlayer *recv;
- CreatureType CVar17;
- uint uVar18;
- TCreature *cr;
- bool bVar19;
- char *pcVar20;
- char *pcVar21;
- char *pcVar22;
- ulong local_c4;
- ulong StatementID;
- ulong local_bc;
- TConnection *Connection_2;
- TPlayer *pl;
- ulong local_98;
- ulong StatementID_1;
- int local_8c;
- int Muting;
- int SpellType;
- int Channel;
- char *Name;
- int iStack_78;
- bool CheckSpamming_local;
- int destX;
- int destY;
- int destZ;
- TPlayer *pl_1;
- int x;
- int y;
- int z;
- TFindCreatures Search;
- Object local_2c [7];
-
- local_8c = 0;
- SpellType = 0;
- Muting = 0;
- // try { // try from 08096019 to 0809706d has its CatchHandler @ 08097073
- this = (TPlayer *)GetCreature(CreatureID);
- if (this == (TPlayer *)0x0) {
- error(&DAT_08100160,CreatureID);
- }
- else {
- local_2c[0].ObjectID = (this->super_TCreature).CrObject.ObjectID;
- GetObjectCoordinates(local_2c,(int *)&pl_1,&x,&y);
- pcVar15 = (this->super_TCreature).Name;
- if (Text == (char *)0x0) {
- pcVar20 = "Talk: Text ist NULL (Sprecher: %s, Modus: %d).\n";
- }
- else {
- sVar2 = strlen(Text);
- if (sVar2 < 0x100) {
- if (((((Mode == 5) || (Mode == 10)) || (Mode == 0xc)) || (Mode == 0xe)) &&
- ((SpellType = __strtol_internal(Addressee,0,10,0), SpellType < 0 ||
- (Channels <= SpellType)))) {
- error(&DAT_0810b8bc,SpellType);
- return;
- }
- pcVar20 = "%s: \"%s\"\n";
- pcVar21 = pcVar15;
- pcVar22 = Text;
- print();
- if ((this->super_TCreature).Type == PLAYER) {
- CVar17 = PLAYER;
- if (CheckSpamming) {
- local_8c = TPlayer::CheckForMuting(this);
- if (0 < local_8c) {
- if (Mode - 1U < 4) {
-LAB_08096fa7:
- pcVar15 = "";
- pTVar12 = (this->super_TCreature).Connection;
- pcVar20 = "You are still muted for %d second%s.";
- if (local_8c != 1) {
- pcVar15 = "s";
- }
- goto LAB_08096d7b;
- }
- if ((Mode == 5) || (Mode == 0xc)) {
- bVar1 = false;
- if ((0 < SpellType) && (bVar1 = true, 7 < SpellType)) {
- bVar1 = false;
- }
- if (bVar1) goto LAB_08096fa7;
- }
- }
- CVar17 = (this->super_TCreature).Type;
- }
- if (CVar17 == PLAYER) {
- CVar17 = PLAYER;
- if (local_8c == 0) {
- pcVar20 = Text;
- Muting = CheckForSpell(CreatureID,Text);
- if (Muting == 1) {
- return;
- }
- if (Muting == 5) {
- return;
- }
- if (Muting < 0) {
- return;
- }
- CVar17 = (this->super_TCreature).Type;
- if (Muting != 0) {
- Mode = 1;
- }
- }
- if (CVar17 == PLAYER) {
- CVar17 = PLAYER;
- if ((char *)Mode == (char *)0x3) {
- if (RoundNr < (this->super_TCreature).EarliestYellRound) {
- puVar13 = (undefined4 *)
- __cxa_allocate_exception(4,pcVar20,pcVar21,pcVar22);
- *puVar13 = 0x31;
- goto LAB_08096dae;
- }
- (this->super_TCreature).EarliestYellRound = RoundNr + 0x1e;
- strUpper(Text);
- CVar17 = (this->super_TCreature).Type;
- }
- if (CVar17 == PLAYER) {
- if (((char *)Mode == (char *)0x5) && (SpellType == 5)) {
- if (RoundNr < (this->super_TCreature).EarliestTradeChannelRound)
- {
- SendMessage((this->super_TCreature).Connection,0x17,
- "You may only place one offer in two minutes.");
- return;
- }
- (this->super_TCreature).EarliestTradeChannelRound =
- RoundNr + 0x78;
- }
- if ((CheckSpamming) && (Muting == 0)) {
- if ((char *)(Mode + -1) < (char *)0x4) {
-LAB_08096e19:
- bVar1 = CheckRight((this->super_TCreature).ID,NO_BANISHMENT)
- ;
- if (!bVar1) {
- local_8c = TPlayer::RecordTalk(this);
- }
- if (0 < local_8c) {
- pTVar12 = (this->super_TCreature).Connection;
- pcVar20 = "You are muted for %d second%s.";
- pcVar15 = "";
- if (local_8c != 1) {
- pcVar15 = "s";
- }
- goto LAB_08096d7b;
- }
- }
- else if (((char *)Mode == (char *)0x5) ||
- ((char *)Mode == (char *)0xc)) {
- bVar1 = false;
- if ((0 < SpellType) && (SpellType < 8)) {
- bVar1 = true;
- }
- if (bVar1) goto LAB_08096e19;
- }
- }
- }
- }
- }
- }
- if (((((char *)Mode == (char *)0x4) || ((char *)Mode == (char *)0x7)) ||
- ((char *)Mode == (char *)0x8)) ||
- (((char *)Mode == (char *)0xb || ((char *)Mode == (char *)0xf)))) {
- if (Addressee == (char *)0x0) {
- pcVar15 = &DAT_08100000;
- }
- else {
- bVar1 = CheckRight((this->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- iVar6 = IdentifyPlayer(Addressee,false,!bVar1,(TPlayer **)&destZ);
- if (iVar6 == -1) {
- puVar13 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar13 = 0x1b;
- goto LAB_08096dae;
- }
- if (iVar6 < 0) {
- if (iVar6 == -2) {
- puVar13 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar13 = 0x1c;
- goto LAB_08096dae;
- }
- }
- else if (iVar6 == 0) {
- if (((char *)Mode == (char *)0x4) &&
- (local_8c = TPlayer::RecordMessage(this,*(ulong *)(destZ + 0x208)),
- 0 < local_8c)) {
- pcVar15 = "";
- if (local_8c != 1) {
- pcVar15 = "s";
- }
- pTVar12 = (this->super_TCreature).Connection;
- pcVar20 =
- "You have addressed too many players. You are muted for %d second%s."
- ;
-LAB_08096d7b:
- SendMessage(pTVar12,0x17,pcVar20,local_8c,pcVar15);
- return;
- }
- if ((char *)Mode == (char *)0xf) {
- SendMessage(*(TConnection **)(destZ + 0x318),0x12,"%s",Text);
- goto LAB_08096bd1;
- }
- uVar3 = (this->super_TCreature).ID;
- if (Text == (char *)0x0) {
- pcVar20 = "LogCommunication: Text ist NULL.\n";
-LAB_08096b2f:
- error(pcVar20);
- StatementID_1 = 0;
- }
- else {
- if (uVar3 == 0) {
- pcVar20 = "LogCommunication: CharacterID ist Null.\n";
- goto LAB_08096b2f;
- }
- ::StatementID = ::StatementID + 1;
- pTVar10 = fifo<TStatement>::append(&Statements);
- pTVar10->StatementID = ::StatementID;
- uVar11 = time((time_t *)0x0);
- pTVar10->TimeStamp = uVar11;
- pTVar10->Channel = 0;
- pTVar10->Mode = Mode;
- pTVar10->CharacterID = uVar3;
- uVar3 = AddDynamicString(Text);
- pTVar10->Reported = false;
- pTVar10->Text = uVar3;
- StatementID_1 = ::StatementID;
- }
- if (((StatementID_1 != 0) && (this != (TPlayer *)0x0)) &&
- (bVar1 = CheckRight((this->super_TCreature).ID,LOG_COMMUNICATION),
- bVar1)) {
- pTVar9 = fifo<TListener>::append(&Listeners);
- pTVar9->StatementID = StatementID_1;
- pTVar9->CharacterID = (this->super_TCreature).ID;
- }
- iVar6 = destZ;
- uVar3 = 0;
- if ((StatementID_1 != 0) && (uVar3 = 0, destZ != 0)) {
- bVar1 = CheckRight(*(ulong *)(destZ + 0x208),LOG_COMMUNICATION);
- if (bVar1) {
- pTVar9 = fifo<TListener>::append(&Listeners);
- pTVar9->StatementID = StatementID_1;
- pTVar9->CharacterID = *(ulong *)(iVar6 + 0x208);
- uVar3 = StatementID_1;
- }
- else {
- uVar3 = 0;
- }
- }
- if ((char *)Mode == (char *)0x7) {
- pTVar12 = *(TConnection **)(destZ + 0x318);
- pcVar15 = "Gamemaster";
- pcVar20 = (char *)0x7;
- }
- else {
- pTVar12 = *(TConnection **)(destZ + 0x318);
- pcVar20 = (char *)Mode;
- }
- SendTalk(pTVar12,uVar3,pcVar15,(int)pcVar20,Text,0);
-LAB_08096bd1:
- if (this == (TPlayer *)0x0) {
- return;
- }
- if ((this->super_TCreature).Type != PLAYER) {
- return;
- }
- pcVar15 = "Gamemaster";
- if ((char *)Mode != (char *)0x8) {
- pcVar15 = (char *)(destZ + 0x214);
- }
- SendMessage((this->super_TCreature).Connection,0x17,
- "Message sent to %s.",pcVar15);
- return;
- }
- pcVar15 = &DAT_080fffc0;
- }
- error(pcVar15);
- goto LAB_08096d9c;
- }
- if ((((char *)(Mode + -1) < (char *)0x3) || ((char *)Mode == (char *)0x10)) ||
- ((char *)Mode == (char *)0x11)) {
- if ((this->super_TCreature).Type == PLAYER) {
- uVar3 = (this->super_TCreature).ID;
- if (Text == (char *)0x0) {
- pcVar20 = "LogCommunication: Text ist NULL.\n";
- }
- else {
- if (uVar3 != 0) {
- ::StatementID = ::StatementID + 1;
- pTVar10 = fifo<TStatement>::append(&Statements);
- pTVar10->StatementID = ::StatementID;
- uVar11 = time((time_t *)0x0);
- pTVar10->TimeStamp = uVar11;
- pTVar10->Channel = 0;
- pTVar10->Mode = Mode;
- pTVar10->CharacterID = uVar3;
- uVar3 = AddDynamicString(Text);
- pTVar10->Reported = false;
- pTVar10->Text = uVar3;
- local_98 = ::StatementID;
- goto LAB_08096778;
- }
- pcVar20 = "LogCommunication: CharacterID ist Null.\n";
- }
- error(pcVar20);
- local_98 = 0;
- }
- else {
- local_98 = 0;
- }
-LAB_08096778:
- if (((char *)Mode == (char *)0x3) || (iVar6 = 7, (char *)Mode == (char *)0x11))
- {
- iVar6 = 0x1e;
- }
- TFindCreatures::TFindCreatures((TFindCreatures *)&z,iVar6,iVar6,(int)pl_1,x,1);
-switchD_08096875_caseD_0:
- uVar3 = TFindCreatures::getNext((TFindCreatures *)&z);
- if (uVar3 != 0) {
- pTVar5 = GetPlayer(uVar3);
- if ((pTVar5 != (TPlayer *)0x0) &&
- (pTVar12 = (pTVar5->super_TCreature).Connection,
- pTVar12 != (TConnection *)0x0)) {
- TConnection::GetPosition(pTVar12,&stack0xffffff88,&destX,&destY);
- uVar14 = (int)pl_1 - iStack_78;
- if (0x7fffffff < uVar14) {
- uVar14 = -uVar14;
- }
- uVar18 = x - destX;
- if (0x7fffffff < uVar18) {
- uVar18 = -uVar18;
- }
- uVar16 = y - destY;
- if (0x7fffffff < uVar16) {
- uVar16 = -uVar16;
- }
- switch(Mode) {
- default:
- goto switchD_08096875_caseD_0;
- case 1:
- case 0x10:
- if ((uVar16 != 0) || (7 < (int)uVar14))
- goto switchD_08096875_caseD_0;
- bVar19 = SBORROW4(uVar18,5);
- iVar6 = uVar18 - 5;
- bVar1 = uVar18 == 5;
- break;
- case 2:
- if (((uVar16 == 0) && ((int)uVar14 < 8)) && ((int)uVar18 < 6)) {
- if (((int)uVar14 < 2) && ((int)uVar18 < 2)) goto LAB_080968e8;
- uVar3 = 0;
- pcVar20 = "pspsps";
- goto LAB_080968de;
- }
- goto switchD_08096875_caseD_0;
- case 3:
- case 0x11:
- if ((0x1e < (int)uVar14) || (0x1e < (int)uVar18))
- goto switchD_08096875_caseD_0;
- if (uVar16 == 0) goto LAB_080968e8;
- if (7 < y) goto switchD_08096875_caseD_0;
- bVar19 = SBORROW4(destY,7);
- iVar6 = destY + -7;
- bVar1 = iVar6 == 0;
- }
- if (bVar1 || bVar19 != iVar6 < 0) {
-LAB_080968e8:
- uVar3 = 0;
- pcVar20 = Text;
- if ((local_98 != 0) && (uVar3 = 0, pTVar5 != (TPlayer *)0x0)) {
- bVar1 = CheckRight((pTVar5->super_TCreature).ID,
- LOG_COMMUNICATION);
- if (bVar1) {
- pTVar9 = fifo<TListener>::append(&Listeners);
- pTVar9->StatementID = local_98;
- pTVar9->CharacterID = (pTVar5->super_TCreature).ID;
- uVar3 = local_98;
- }
- else {
- uVar3 = 0;
- }
- }
-LAB_080968de:
- SendTalk(pTVar12,uVar3,pcVar15,Mode,(int)pl_1,x,y,pcVar20);
- }
- }
- goto switchD_08096875_caseD_0;
- }
- goto LAB_080961c4;
- }
- if ((char *)Mode != (char *)0x9) {
- if ((char *)Mode == (char *)0xd) {
- pTVar12 = GetFirstConnection();
- while (pTVar12 != (TConnection *)0x0) {
- if (pTVar12->State - CONNECTION_LOGIN < 4) {
- SendMessage(pTVar12,0x12,Text);
- }
- pTVar12 = GetNextConnection();
- }
- goto LAB_080961c4;
- }
- if ((((char *)Mode == (char *)0x5) || ((char *)Mode == (char *)0xa)) ||
- ((char *)Mode == (char *)0xc)) {
- if ((char *)Mode == (char *)0xe) goto LAB_08096253;
- uVar3 = (this->super_TCreature).ID;
- if (Text == (char *)0x0) {
- pcVar20 = "LogCommunication: Text ist NULL.\n";
-LAB_080964fe:
- error(pcVar20);
- local_c4 = 0;
- }
- else {
- if (uVar3 == 0) {
- pcVar20 = "LogCommunication: CharacterID ist Null.\n";
- goto LAB_080964fe;
- }
- ::StatementID = ::StatementID + 1;
- pTVar10 = fifo<TStatement>::append(&Statements);
- pTVar10->StatementID = ::StatementID;
- uVar11 = time((time_t *)0x0);
- pTVar10->TimeStamp = uVar11;
- pTVar10->Mode = Mode;
- pTVar10->CharacterID = uVar3;
- pTVar10->Channel = SpellType;
- uVar3 = AddDynamicString(Text);
- pTVar10->Reported = false;
- pTVar10->Text = uVar3;
- local_c4 = ::StatementID;
- }
- }
- else {
- if ((char *)Mode != (char *)0xe) {
- error(&DAT_080ffe40,Mode);
- goto LAB_080961c4;
- }
-LAB_08096253:
- local_c4 = 0;
- }
- if ((SpellType < 0) || (Channels <= SpellType)) {
- error(&DAT_080ffea0,SpellType);
- bVar1 = false;
- }
- else {
- bVar1 = true;
- if (7 < SpellType) {
- pTVar7 = vector<TChannel>::operator()(&::Channel,SpellType);
- bVar1 = pTVar7->Moderator != 0;
- }
- }
- uVar3 = 0;
- if (bVar1) {
- CurrentSubscriberNumber = 0;
- CurrentChannelID = SpellType;
- bVar1 = ChannelActive(SpellType);
- uVar3 = 0;
- if (bVar1) {
- pTVar7 = vector<TChannel>::operator()(&::Channel,CurrentChannelID);
- iVar6 = CurrentSubscriberNumber;
- if (CurrentSubscriberNumber < pTVar7->Subscribers) {
- CurrentSubscriberNumber = CurrentSubscriberNumber + 1;
- puVar8 = vector<>::operator()(&pTVar7->Subscriber,iVar6);
- uVar3 = *puVar8;
- }
- else {
- uVar3 = 0;
- }
- }
- }
- while (uVar3 != 0) {
- pTVar5 = GetPlayer(uVar3);
- if ((pTVar5 != (TPlayer *)0x0) &&
- ((SpellType != 0 ||
- (((this->super_TCreature).Type == PLAYER &&
- (iVar6 = strcmp(this->Guild,pTVar5->Guild), iVar6 == 0)))))) {
- if ((local_c4 != 0) &&
- (bVar1 = CheckRight((pTVar5->super_TCreature).ID,LOG_COMMUNICATION),
- bVar1)) {
- pTVar9 = fifo<TListener>::append(&Listeners);
- pTVar9->StatementID = local_c4;
- pTVar9->CharacterID = (pTVar5->super_TCreature).ID;
- }
- bVar1 = false;
- if ((3 < SpellType) && (SpellType < 8)) {
- bVar1 = true;
- }
- if ((bVar1) || (SpellType == 2)) {
-LAB_08096325:
- uVar3 = local_c4;
- }
- else {
- bVar1 = CheckRight((pTVar5->super_TCreature).ID,LOG_COMMUNICATION);
- uVar3 = 0;
- if (bVar1) goto LAB_08096325;
- }
- pTVar12 = (pTVar5->super_TCreature).Connection;
- SendTalk(pTVar12,uVar3,(char *)pTVar12,uVar3,(int)pcVar15,(char *)Mode);
- }
- if ((CurrentChannelID < 0) || (Channels <= CurrentChannelID)) {
- error(&DAT_080ffea0,CurrentChannelID);
- bVar1 = false;
- }
- else {
- bVar1 = true;
- if (7 < CurrentChannelID) {
- pTVar7 = vector<TChannel>::operator()(&::Channel,CurrentChannelID);
- bVar1 = pTVar7->Moderator != 0;
- }
- }
- uVar3 = 0;
- if (bVar1) {
- pTVar7 = vector<TChannel>::operator()(&::Channel,CurrentChannelID);
- iVar6 = CurrentSubscriberNumber;
- if (CurrentSubscriberNumber < pTVar7->Subscribers) {
- CurrentSubscriberNumber = CurrentSubscriberNumber + 1;
- puVar8 = vector<>::operator()(&pTVar7->Subscriber,iVar6);
- uVar3 = *puVar8;
- }
- else {
- uVar3 = 0;
- }
- }
- }
- goto LAB_080961c4;
- }
- uVar3 = (this->super_TCreature).ID;
- if (Text == (char *)0x0) {
- pcVar20 = "LogCommunication: Text ist NULL.\n";
-LAB_080965e5:
- error(pcVar20);
- local_bc = 0;
- }
- else {
- if (uVar3 == 0) {
- pcVar20 = "LogCommunication: CharacterID ist Null.\n";
- goto LAB_080965e5;
- }
- ::StatementID = ::StatementID + 1;
- pTVar10 = fifo<TStatement>::append(&Statements);
- pTVar10->StatementID = ::StatementID;
- uVar11 = time((time_t *)0x0);
- pTVar10->TimeStamp = uVar11;
- pTVar10->Channel = 0;
- pTVar10->Mode = 9;
- pTVar10->CharacterID = uVar3;
- uVar3 = AddDynamicString(Text);
- pTVar10->Reported = false;
- pTVar10->Text = uVar3;
- local_bc = ::StatementID;
- }
- pTVar12 = GetFirstConnection();
- while (pTVar12 != (TConnection *)0x0) {
- if (pTVar12->State - CONNECTION_LOGIN < 4) {
- pTVar5 = TConnection::GetPlayer(pTVar12);
- uVar3 = 0;
- if ((local_bc != 0) && (uVar3 = 0, pTVar5 != (TPlayer *)0x0)) {
- bVar1 = CheckRight((pTVar5->super_TCreature).ID,LOG_COMMUNICATION);
- uVar3 = 0;
- if (bVar1) {
- pTVar9 = fifo<TListener>::append(&Listeners);
- pTVar9->StatementID = local_bc;
- pTVar9->CharacterID = (pTVar5->super_TCreature).ID;
- uVar3 = local_bc;
- }
- }
- SendTalk(pTVar12,uVar3,pcVar15,9,Text,0);
- }
- pTVar12 = GetNextConnection();
- }
-LAB_080961c4:
- if (((char *)Mode == (char *)0x1) && ((this->super_TCreature).Type == PLAYER)) {
- TFindCreatures::TFindCreatures((TFindCreatures *)&z,3,3,CreatureID,2);
- while (uVar3 = TFindCreatures::getNext((TFindCreatures *)&z), uVar3 != 0) {
- pTVar4 = GetCreature(uVar3);
- if (pTVar4 == (TCreature *)0x0) {
- error("Talk: Kreatur existiert nicht.\n");
- }
- else if (pTVar4->posz == y) {
- (*pTVar4->_vptr_TCreature[6])(pTVar4,CreatureID,Text);
- }
- }
- }
- return;
- }
- pcVar20 = &DAT_081000e0;
- Mode = sVar2;
- }
- error(pcVar20,pcVar15,Mode);
- }
-LAB_08096d9c:
- puVar13 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar13 = 0xffffffff;
-LAB_08096dae:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar13,&RESULT::typeinfo,0);
-}
-
-
-
void Use(ulong CreatureID,Object *Obj1,Object *Obj2,uchar Info)
{
diff --git a/src/info.hh b/src/info.hh
index 0a7f919..863c500 100644
--- a/src/info.hh
+++ b/src/info.hh
@@ -15,6 +15,7 @@ enum HouseList: uint8 {
const char *GetLiquidName(int LiquidType);
uint8 GetLiquidColor(int LiquidType);
const char *GetName(Object Obj);
+const char *GetInfo(Object Obj);
int GetWeight(Object Obj, int Count);
int GetCompleteWeight(Object Obj);
int GetRowWeight(Object Obj);
diff --git a/src/operate.cc b/src/operate.cc
index 5f7d4d3..1e1f9a6 100644
--- a/src/operate.cc
+++ b/src/operate.cc
@@ -1804,3 +1804,648 @@ void Missile(Object Start, Object Dest, int Type){
GetObjectCoordinates(Dest, &DestX, &DestY, &DestZ);
AnnounceMissile(StartX, StartY, StartZ, DestX, DestY, DestZ, Type);
}
+
+void Look(uint32 CreatureID, Object Obj){
+ // TODO(fusion): Honestly one of the first things we should focus on, after
+ // the server is running, is to implement a small stack buffer writer/formatter
+ // to retire `strcpy`, `strcat`, and `sprintf`.
+
+ TPlayer *Player = GetPlayer(CreatureID);
+ if(Player == NULL){
+ error("Look: Kreatur existiert nicht.\n");
+ throw ERROR;
+ }
+
+ if(!Obj.exists()){
+ error("Look: Objekt existiert nicht.\n");
+ throw ERROR;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ if(ObjType.isCreatureContainer()){
+ TCreature *Target = GetCreature(Obj);
+ if(Target == NULL){
+ error("Look: Object %d hat keine Kreatur!\n", ObjType.TypeID);
+ return;
+ }
+
+ if(Target->Type == PLAYER){
+ TPlayer *TargetPlayer = (TPlayer*)Target;
+ bool Yourself = (CreatureID == TargetPlayer->ID);
+ char Pronoun[4] = {};
+ char Name[50] = {};
+ char Vocation[50] = {};
+
+ if(TargetPlayer->Sex == 1){
+ strcpy(Pronoun, "He");
+ }else{
+ strcpy(Pronoun, "She");
+ }
+
+ uint8 Profession = TargetPlayer->GetActiveProfession();
+ if(Yourself){
+ strcpy(Name, "yourself");
+
+ if(Profession != PROFESSION_NONE){
+ char Help[30];
+ GetProfessionName(Help, Profession, true, false);
+ snprintf(Vocation, sizeof(Vocation), "You are %s", Help);
+ }else{
+ strcpy(Vocation, "You have no vocation");
+ }
+ }else{
+ int Level = 1;
+ if(TargetPlayer->Skills[SKILL_LEVEL] != NULL){
+ Level = TargetPlayer->Skills[SKILL_LEVEL]->Get();
+ }
+ snprintf(Name, sizeof(Name), "%s (Level %d)", TargetPlayer->Name, Level);
+
+ if(Profession != PROFESSION_NONE){
+ char Help[30];
+ GetProfessionName(Help, Profession, true, false);
+ snprintf(Vocation, sizeof(Vocation), "%s is %s", Pronoun, Help);
+ }else{
+ snprintf(Vocation, sizeof(Vocation), "%s has no vocation", Pronoun);
+ }
+ }
+
+ if(TargetPlayer->Guild[0] != 0){
+ char Membership[200] = {};
+ if(Yourself){
+ strcpy(Membership, "You are ");
+ }else{
+ snprintf(Membership, sizeof(Membership), "%s id ", Pronoun);
+ }
+
+ if(TargetPlayer->Rank[0] != 0){
+ strcat(Membership, TargetPlayer->Rank);
+ }else{
+ strcat(Membership, "a member");
+ }
+
+ strcat(Membership, " of the ");
+ strcat(Membership, TargetPlayer->Guild);
+ if(TargetPlayer->Title[0] != 0){
+ strcat(Membership, " (");
+ strcat(Membership, TargetPlayer->Title);
+ strcat(Membership, ")");
+ }
+
+ SendMessage(Player->Connection, TALK_INFO_MESSAGE,
+ "You see %s. %s. %s.", Name, Vocation, Membership);
+ }else{
+ SendMessage(Player->Connection, TALK_INFO_MESSAGE,
+ "You see %s. %s.", Name, Vocation);
+ }
+ }else{
+ SendMessage(Player->Connection, TALK_INFO_MESSAGE, "You see %s.", Target->Name);
+ }
+ }else{
+ char Description[500] = {};
+ char Help[500] = {};
+
+ snprintf(Description, sizeof(Description), "You see %s", GetName(Obj));
+
+ if(ObjType.getFlag(LEVELDOOR)){
+ snprintf(Help, sizeof(Help), " for level %u",
+ Obj.getAttribute(DOORLEVEL));
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(CONTAINER)){
+ snprintf(Help, sizeof(Help), " (Vol:%u)",
+ ObjType.getAttribute(CAPACITY));
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(WEAPON)){
+ snprintf(Help, sizeof(Help), " (Atk:%u Def:%u)",
+ ObjType.getAttribute(WEAPONATTACKVALUE),
+ ObjType.getAttribute(WEAPONDEFENDVALUE));
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(THROW)){
+ snprintf(Help, sizeof(Help), " (Atk:%u Def:%u)",
+ ObjType.getAttribute(THROWATTACKVALUE),
+ ObjType.getAttribute(THROWDEFENDVALUE));
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(SHIELD)){
+ snprintf(Help, sizeof(Help), " (Def:%u)",
+ ObjType.getAttribute(SHIELDDEFENDVALUE));
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(ARMOR)){
+ snprintf(Help, sizeof(Help), " (Arm:%u)",
+ ObjType.getAttribute(ARMORVALUE));
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(KEY)){
+ snprintf(Help, sizeof(Help), " (Key:%04u)",
+ Obj.getAttribute(KEYNUMBER));
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(KEYDOOR) && CheckRight(Player->ID, SHOW_KEYHOLE_NUMBERS)){
+ snprintf(Help, sizeof(Help), " (Door:%04u)",
+ Obj.getAttribute(KEYHOLENUMBER));
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(SHOWDETAIL)){
+ if(ObjType.getFlag(WEAROUT) && ObjType.getAttribute(TOTALUSES) > 1){
+ uint32 RemainingUses = Obj.getAttribute(REMAININGUSES);
+ snprintf(Help, sizeof(Help), " that has %u charge%s left",
+ RemainingUses, (RemainingUses != 1 ? "s" : ""));
+ strcat(Description, Help);
+ }else if(ObjType.getFlag(EXPIRE) || ObjType.getFlag(EXPIRESTOP)){
+ uint32 SecondsLeft;
+ if(ObjType.getFlag(EXPIRE)){
+ SecondsLeft = CronInfo(Obj, false);
+ }else{
+ SecondsLeft = Obj.getAttribute(SAVEDEXPIRETIME);
+ }
+
+ uint32 MinutesLeft = (SecondsLeft + 59) / 60;
+ if(MinutesLeft == 0){
+ snprintf(Help, sizeof(Help), " that is brand-new");
+ }else{
+ snprintf(Help, sizeof(Help), " that has energy for %u minutes%s left",
+ MinutesLeft, (MinutesLeft != 1 ? "s" : ""));
+ }
+ strcat(Description, Help);
+ }else{
+ error("Look: Objekt %d hat Flag SHOWDETAIL, aber weder WEAROUT noch EXPIRE.\n", ObjType.TypeID);
+ }
+ }
+
+ if(ObjType.getFlag(RESTRICTLEVEL) || ObjType.getFlag(RESTRICTPROFESSION)){
+ strcat(Description, ".\nIt can only be wielded by ");
+ if(ObjType.getFlag(RESTRICTPROFESSION)){
+ int ProfessionCount = 0;
+ uint32 ProfessionMask = ObjType.getAttribute(PROFESSIONS);
+
+ if(ProfessionMask & 1){
+ ProfessionCount += 1;
+ strcpy(Help, "players without vocation");
+ }else{
+ strcpy(Help, "");
+ }
+
+ // NOTE(fusion): We're iterating professions in reverse because
+ // the string is built in reverse to avoid extra processing for
+ // adding commas and the final "and ...".
+ for(int Profession = 4; Profession >= 1; Profession -= 1){
+ if((ProfessionMask & (1 << Profession)) == 0){
+ continue;
+ }
+
+ char Temp[200] = {};
+ if(ProfessionCount == 1){
+ snprintf(Temp, sizeof(Temp), " and %s", Help);
+ }else if(ProfessionCount > 1){
+ snprintf(Temp, sizeof(Temp), ", %s", Help);
+ }
+
+ switch(Profession){
+ case PROFESSION_KNIGHT: strcpy(Help, "knights"); break;
+ case PROFESSION_PALADIN: strcpy(Help, "paladins"); break;
+ case PROFESSION_SORCERER: strcpy(Help, "sorcerers"); break;
+ case PROFESSION_DRUID: strcpy(Help, "druids"); break;
+ }
+
+ strcat(Help, Temp);
+ }
+ }else{
+ strcpy(Help, "players");
+ }
+
+ if(ObjType.getFlag(RESTRICTLEVEL)){
+ char Temp[200] = {};
+ snprintf(Temp, sizeof(Temp), " of level %u or higher",
+ ObjType.getAttribute(MINIMUMLEVEL));
+ strcat(Help, Temp);
+ }
+
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(RUNE)){
+ int MagicLevel;
+ GetMagicItemDescription(Obj, Help, &MagicLevel);
+ if(MagicLevel != 0){
+ char Temp[200] = {};
+ snprintf(Temp, sizeof(Temp), " for magic level %d", MagicLevel);
+ strcat(Description, Temp);
+ }
+
+ strcat(Description, ". It\'s an \"");
+ strcat(Description, Help);
+ strcat(Description, "\"-spell");
+
+ snprintf(Help, sizeof(Help), " (%ux)", Obj.getAttribute(CHARGES));
+ strcat(Description, Help);
+ }
+
+ if(ObjType.getFlag(BED)){
+ uint32 Sleeper = Obj.getAttribute(TEXTSTRING);
+ if(Sleeper != 0){
+ snprintf(Help, sizeof(Help), ". %s is sleeping there",
+ GetDynamicString(Sleeper));
+ strcat(Description, Help);
+ }
+ }
+
+ if(ObjType.getFlag(NAMEDOOR)){
+ int ObjX, ObjY, ObjZ;
+ GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ);
+
+ uint16 HouseID = GetHouseID(ObjX, ObjY, ObjZ);
+ if(HouseID != 0){
+ // TODO(fusion): Make `GetHouseOwner` return "Nobody" when there
+ // is no owner name.
+ snprintf(Help, sizeof(Help),
+ ". It belongs to house \'%s\'. %s owns this house",
+ GetHouseName(HouseID), GetHouseOwner(HouseID));
+ strcat(Description, Help);
+ }else{
+ error("Look: NameDoor auf [%d,%d,%d] gehört zu keinem Haus.\n", ObjX, ObjY, ObjZ);
+ }
+ }
+
+ strcat(Description, ".");
+
+ if((ObjType.getFlag(LIQUIDCONTAINER) && Obj.getAttribute(CONTAINERLIQUIDTYPE) == LIQUID_NONE)
+ || (ObjType.getFlag(LIQUIDPOOL) && Obj.getAttribute(POOLLIQUIDTYPE) == LIQUID_NONE)){
+ strcat(Description, " It is empty.");
+ }
+
+ // TODO(fusion): This looks like an inlined function because we'd have
+ // already returned at the beginning if `CreatureID` was zero.
+ if(CreatureID == 0 || ObjectInRange(CreatureID, Obj, 1)){
+ if(ObjType.getFlag(TAKE) && GetWeight(Obj, -1) > 0){
+ int ObjWeight = GetCompleteWeight(Obj);
+ if(ObjType.getFlag(CUMULATIVE)
+ && Obj.getAttribute(AMOUNT) > 1
+ && IsCountable(ObjType.getName(1))){
+ snprintf(Help, sizeof(Help), "\nThey weigh %d.%02d oz.",
+ ObjWeight / 100, ObjWeight % 100);
+ }else{
+ snprintf(Help, sizeof(Help), "\nIt weighs %d.%02d oz.",
+ ObjWeight / 100, ObjWeight % 100);
+ }
+ strcat(Description, Help);
+ }
+
+ const char *ObjInfo = GetInfo(Obj);
+ if(ObjInfo != NULL){
+ snprintf(Help, sizeof(Help), "\n%s.", ObjInfo);
+ strcat(Description, Help);
+ }
+ }
+
+ if(ObjType.getFlag(TEXT)){
+ int FontSize = (int)ObjType.getAttribute(FONTSIZE);
+ if(FontSize == 0){
+ uint32 Text = Obj.getAttribute(TEXTSTRING);
+ if(Text != 0){
+ snprintf(Help, sizeof(Help), "\n%s.", GetDynamicString(Text));
+ strcat(Description, Help);
+ }
+ }else if(FontSize >= 2){
+ uint32 Text = Obj.getAttribute(TEXTSTRING);
+ if(Text != 0){
+ // TODO(fusion): Again, `CreatureID` can't be zero here.
+ if(CreatureID == 0 || ObjectInRange(CreatureID, Obj, FontSize)){
+ uint32 Editor = Obj.getAttribute(EDITOR);
+ if(Editor != 0){
+ snprintf(Help, sizeof(Help), "\n%s has written: %s",
+ GetDynamicString(Editor),
+ GetDynamicString(Text));
+ }else{
+ snprintf(Help, sizeof(Help), "\nYou read: %s",
+ GetDynamicString(Text));
+ }
+ strcat(Description, Help);
+ }else{
+ strcat(Description, "\nYou are too far away to read it.");
+ }
+ }else{
+ strcat(Description, "\nNothing is written on it.");
+ }
+ }
+ }
+
+ SendMessage(Player->Connection, TALK_INFO_MESSAGE, "%s", Description);
+ }
+}
+
+void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text, bool CheckSpamming){
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("Talk: Übergebene Kreatur %d existiert nicht.\n", CreatureID);
+ throw ERROR;
+ }
+
+ if(Text == NULL){
+ error("Talk: Text ist NULL (Sprecher: %s, Modus: %d).\n", Creature->Name, Mode);
+ throw ERROR;
+ }
+
+ int TextLen = (int)strlen(Text);
+ if(TextLen >= 256){
+ error("Talk: Text ist zu lang (Sprecher: %s, Länge: %d).\n", Creature->Name, TextLen);
+ throw ERROR;
+ }
+
+ int Channel = 0;
+ if(Mode == TALK_CHANNEL_CALL
+ || Mode == TALK_GAMEMASTER_CHANNELCALL
+ || Mode == TALK_HIGHLIGHT_CHANNELCALL
+ || Mode == TALK_ANONYMOUS_CHANNELCALL){
+ // TODO(fusion): Check if `Addressee` is NULL?
+ Channel = atoi(Addressee);
+ if(Channel < 0 || Channel >= Channels){
+ error("Talk: Ungültiger Kanal %d.\n", Channel);
+ return;
+ }
+ }
+
+ print(2, "%s: \"%s\"\n", Creature->Name, Text);
+
+ if(Creature->Type == PLAYER){
+ TPlayer *Player = (TPlayer*)Creature;
+
+ // TODO(fusion): Some `IsTalkMuteable` inlined function?
+ bool TalkMuteable = Mode == TALK_SAY
+ || Mode == TALK_WHISPER
+ || Mode == TALK_YELL
+ || Mode == TALK_PRIVATE_MESSAGE
+ || ((Mode == TALK_CHANNEL_CALL
+ || Mode == TALK_HIGHLIGHT_CHANNELCALL)
+ && Channel >= 1 && Channel <= 7);
+
+ int Muting = 0;
+ if(CheckSpamming){
+ Muting = Player->CheckForMuting();
+ if(Muting > 0 && TalkMuteable){
+ SendMessage(Player->Connection, TALK_FAILURE_MESSAGE,
+ "You are still muted for %d second%s.",
+ Muting, (Muting != 1 ? "s" : ""));
+ return;
+ }
+ }
+
+ int SpellType = 0;
+ if(Muting == 0){
+ SpellType = CheckForSpell(CreatureID, Text);
+ if(SpellType < 0 || SpellType == 1 || SpellType == 5){
+ return;
+ }
+
+ if(SpellType != 0){
+ Mode = TALK_SAY;
+ }
+ }
+
+ if(Mode == TALK_YELL){
+ if(Player->EarliestYellRound > RoundNr){
+ throw EXHAUSTED;
+ }
+
+ // TODO(fusion): This would be valid if `Text` was `char*`, but I
+ // wanted to improve the quality of string handling and parameters
+ // across the board, and now we need some scratch buffer to actually
+ // modify the text.
+ strUpper(Text);
+ }
+
+ if(Mode == TALK_CHANNEL_CALL && Channel == 5){
+ if(Player->EarliestTradeChannelRound > RoundNr){
+ SendMessage(Player->Connection, TALK_FAILURE_MESSAGE,
+ "You may only place one offer in two minutes.");
+ return;
+ }
+
+ Player->EarliestTradeChannelRound = RoundNr + 120;
+ }
+
+ if(CheckSpamming && SpellType == 0 && TalkMuteable
+ && !CheckRight(Player->ID, NO_BANISHMENT)){
+ Muting = Player->RecordTalk();
+ if(Muting > 0){
+ SendMessage(Player->Connection, TALK_FAILURE_MESSAGE,
+ "You are muted for %d second%s.",
+ Muting, (Muting != 1 ? "s" : ""));
+ return;
+ }
+ }
+ }
+
+ if(Mode == TALK_PRIVATE_MESSAGE
+ || Mode == TALK_GAMEMASTER_ANSWER
+ || Mode == TALK_PLAYER_ANSWER
+ || Mode == TALK_GAMEMASTER_MESSAGE
+ || Mode == TALK_GAMEMASTER_MESSAGE
+ || Mode == TALK_ANONYMOUS_MESSAGE){
+ // TODO(fusion): These assumed the creature was a player but it wasn't checked.
+ if(Creature->Type != PLAYER){
+ error("Talk: Expected player creature for message talk modes.");
+ throw ERROR;
+ }
+
+ if(Addressee == NULL){
+ error("Talk: Adressat für Botschaft nicht angegeben.\n");
+ throw ERROR;
+ }
+
+ TPlayer *Player = (TPlayer*)Creature;
+ TPlayer *Receiver;
+ bool IgnoreGamemasters = !CheckRight(Player->ID, READ_GAMEMASTER_CHANNEL);
+ switch(IdentifyPlayer(Addressee, false, IgnoreGamemasters, &Receiver)){
+ case 0: break; // PLAYERFOUND ?
+ case -1: throw PLAYERNOTONLINE;
+ case -2: throw NAMEAMBIGUOUS;
+ default:{
+ error("Talk: Ungültiger Rückgabewert von IdentifyPlayer.\n");
+ throw ERROR;
+ }
+ }
+
+ if(Mode == TALK_PRIVATE_MESSAGE){
+ Muting = Player->RecordMessage(Receiver->ID);
+ if(Muting > 0){
+ SendMessage(Player->Connection, TALK_FAILURE_MESSAGE,
+ "You have addressed too many players. You are muted for %d second%s.",
+ Muting, (Muting != 1 ? "s" : ""));
+ return;
+ }
+ }
+
+ if(Mode != TALK_ANONYMOUS_MESSAGE){
+ uint32 StatementID = LogCommunication(CreatureID, Mode, 0, Text);
+ LogListener(StatementID, Player);
+ SendTalk(Receiver->Connection, LogListener(StatementID, Receiver),
+ (Mode == TALK_GAMEMASTER_ANSWER ? "Gamemaster" : Player->Name),
+ Mode, Text, 0);
+ }else{
+ SendMessage(Receiver->Connection, TALK_ADMIN_MESSAGE, "%s", Text);
+ }
+
+ SendMessage(Player->Connection, TALK_FAILURE_MESSAGE, "Message sent to %s.",
+ (Mode == TALK_PLAYER_ANSWER ? "Gamemaster" : Receiver->Name));
+ return;
+ }else if(Mode == TALK_SAY
+ || Mode == TALK_WHISPER
+ || Mode == TALK_YELL
+ || Mode == TALK_ANIMAL_LOW
+ || Mode == TALK_ANIMAL_LOUD){
+ uint32 StatementID;
+ if(Creature->Type == PLAYER){
+ StatementID = LogCommunication(CreatureID, Mode, 0, Text);
+ }else{
+ StatementID = 0;
+ }
+
+ int Radius;
+ if(Mode == TALK_YELL || Mode == TALK_ANIMAL_LOUD){
+ Radius = 30; // RANGE_YELL ?
+ }else{
+ Radius = 7; // RANGE_SAY ?
+ }
+
+ TFindCreatures Search(Radius, Radius, Creature->posx, Creature->posy, FIND_PLAYERS);
+ while(true){
+ uint32 SpectatorID = Search.findNext();
+ if(SpectatorID == 0){
+ break;
+ }
+
+ TPlayer *Spectator = GetPlayer(SpectatorID);
+ if(Spectator == NULL || Spectator->Connection == NULL){
+ continue;
+ }
+
+ int DistanceX = std::abs(Spectator->posx - Creature->posx);
+ int DistanceY = std::abs(Spectator->posy - Creature->posy);
+ int DistanceZ = std::abs(Spectator->posz - Creature->posz);
+ if(Mode == TALK_SAY || Mode == TALK_ANIMAL_LOW){
+ if(DistanceX > 7 || DistanceY > 5 || DistanceZ > 0){
+ continue;
+ }
+ }else if(Mode == TALK_WHISPER){
+ if(DistanceX > 7 || DistanceY > 5 || DistanceZ > 0){
+ continue;
+ }
+
+ if(DistanceX > 1 && DistanceY > 1){
+ SendTalk(Spectator->Connection, 0, Creature->Name, Mode,
+ Creature->posx, Creature->posy, Creature->posz,
+ "pspsps");
+ continue;
+ }
+ }else if(Mode == TALK_YELL || Mode == TALK_ANIMAL_LOUD){
+ if(DistanceX > 30 || DistanceY > 30){
+ continue;
+ }
+
+ // TODO(fusion): This seems to be correct. Underground yells
+ // aren't multi floor.
+ if(DistanceZ > 0 && (Spectator->posz > 7 || Creature->posz > 7)){
+ continue;
+ }
+ }
+
+ SendTalk(Spectator->Connection,
+ LogListener(StatementID, Spectator),
+ Creature->Name, Mode,
+ Creature->posx, Creature->posy, Creature->posz, Text);
+ }
+ }else if(Mode == TALK_GAMEMASTER_BROADCAST){
+ uint32 StatementID = LogCommunication(CreatureID, Mode, 0, Text);
+ TConnection *Connection = GetFirstConnection();
+ while(Connection != NULL){
+ // TODO(fusion): Same as `AdvanceGame`. Definitely some inlined
+ // function to check whether the connection is in a valid state.
+ if(Connection->State == CONNECTION_LOGIN
+ || Connection->State == CONNECTION_GAME
+ || Connection->State == CONNECTION_DEAD
+ || Connection->State == CONNECTION_LOGOUT){
+ SendTalk(Connection,
+ LogListener(StatementID, Connection->GetPlayer()),
+ Creature->Name, Mode, Text, 0);
+ }
+
+ Connection = GetNextConnection();
+ }
+ }else if(Mode == TALK_ANONYMOUS_BROADCAST){
+ TConnection *Connection = GetFirstConnection();
+ while(Connection != NULL){
+ // TODO(fusion): Same as above.
+ if(Connection->State == CONNECTION_LOGIN
+ || Connection->State == CONNECTION_GAME
+ || Connection->State == CONNECTION_DEAD
+ || Connection->State == CONNECTION_LOGOUT){
+ SendMessage(Connection, TALK_ADMIN_MESSAGE, Text);
+ }
+
+ Connection = GetNextConnection();
+ }
+ }else if(Mode == TALK_CHANNEL_CALL
+ || Mode == TALK_GAMEMASTER_CHANNELCALL
+ || Mode == TALK_HIGHLIGHT_CHANNELCALL
+ || Mode == TALK_ANONYMOUS_CHANNELCALL){
+ uint32 StatementID = 0;
+ if(Mode != TALK_ANONYMOUS_CHANNELCALL){
+ StatementID = LogCommunication(CreatureID, Mode, Channel, Text);
+ }
+
+ // TODO(fusion): We should probably cleanup these global iterators.
+ for(uint32 SubscriberID = GetFirstSubscriber(Channel);
+ SubscriberID != 0;
+ SubscriberID = GetNextSubscriber()){
+ TPlayer *Subscriber = GetPlayer(SubscriberID);
+ if(Subscriber == NULL){
+ continue;
+ }
+
+ // TODO(fusion): We should probably review this. What if both player
+ // guild names are empty? Is it checked elsewhere?
+ if(Channel == 0 && (Creature->Type != PLAYER
+ || strcmp(((TPlayer*)Creature)->Guild, Subscriber->Guild) != 0)){
+ continue;
+ }
+
+ // TODO(fusion): There was some weird logic here to select the statement
+ // id and it didn't seem to make a difference since `LogListener` was
+ // always called, regardless.
+ SendTalk(Subscriber->Connection,
+ LogListener(StatementID, Subscriber),
+ Creature->Name, Mode, Channel, Text);
+ }
+ }else{
+ // TODO(fusion): Put private messages into this if-else chain.
+ error("Talk: Ungültiger Sprechmodus %d.\n", Mode);
+ }
+
+ if(Mode == TALK_SAY && Creature->Type == PLAYER){
+ TFindCreatures Search(3, 3, CreatureID, FIND_NPCS);
+ while(true){
+ uint32 SpectatorID = Search.getNext();
+ if(SpectatorID == 0){
+ break;
+ }
+
+ TCreature *Spectator = GetCreature(SpectatorID);
+ if(Spectator != NULL){
+ Spectator->TalkStimulus(CreatureID, Text);
+ }else{
+ error("Talk: Kreatur existiert nicht.\n");
+ }
+ }
+ }
+}
diff --git a/src/stubs.hh b/src/stubs.hh
index c8b2e63..cb06608 100644
--- a/src/stubs.hh
+++ b/src/stubs.hh
@@ -30,7 +30,10 @@ extern void CreatePool(Object Con, ObjectType Type, uint32 Value);
extern void GetExitPosition(uint16 HouseID, int *x, int *y, int *z);
extern TConnection *GetFirstConnection(void);
extern TConnection *GetNextConnection(void);
+extern const char *GetHouseName(uint16 HouseID);
+extern const char *GetHouseOwner(uint16 HouseID);
extern TPlayer *GetPlayer(uint32 CreatureID);
+extern void GetProfessionName(char *Buffer, int Profession, bool Article, bool Capitals);
extern int IdentifyPlayer(const char *Name, bool ExactMatch, bool IgnoreGamemasters, TPlayer **Player);
extern void InitLog(const char *ProtocolName);
extern void KickGuest(uint16 HouseID, TPlayer *Host, TPlayer *Guest);