ID:144450
 
Code:
        
//Attack Code
Attack(mob/player/P,mob/monsters/M,list/monstergroup)
var/mob/monsters/enemy = Targetting(P,M,monstergroup)
var/damage = (P.tempstr * P.tempdex + rand(-10,10)) - (enemy.tempstr * enemy.tempdex + rand(-10,10))
var/chancehit = (P.tempagl * (rand(7,14)/10) + rand(-100,100)) - (enemy.tempagl * (rand(7,14)/10) + rand(-100,100))
var/chancehit2 = rand(0,2)
var/critical = (P.tempstr * P.tempagl * P.tempdex + rand(0,50)) - (enemy.tempstr * enemy.tempagl * enemy.tempdex + rand(0,50))
var/realchance = rand(1,20)
if(M.defending)
damage /= 2
critical /= 2
damage = round(damage)
critical = round(critical)
if(realchance == 5 || realchance == 15)
if(critical >= 1)
var/criticalchance = (P.tempagl * (rand(10,20)/10) + rand(-50,50)) - (enemy.tempagl * (rand(10,20)/10) + rand(-50,50))
if(criticalchance >= 1)
DamageAddInfo(P,"You attack [enemy]!","Critical! ","[critical] damage!",'attack.wav','hit.wav',"Critical!")
enemy.hp -= critical
sleep(12)
if(enemy.hp <= 0)
P.Deathcheck(P,M,monstergroup)
else
DamageAddInfo(P,"You attack [enemy]!","Critical! ","Miss!",'attack.wav','dodge.wav',"Critical!")
sleep(12)
else
DamageAddInfo(P,"You attack [enemy]!","Critical! ","Miss!",'attack.wav','dodge.wav',"Critical!")
sleep(12)
else if(chancehit <= 0)
if(chancehit2 == 1)
DamageAddInfo(P,"You attack [enemy]!","1 damage!",'attack.wav','hit.wav')
enemy.hp --
sleep(12)
if(enemy.hp <= 0)
P.Deathcheck(P,M,monstergroup)
else
DamageAddInfo(P,"You attack [enemy]!","Miss!",'attack.wav','dodge.wav')
sleep(12)
else
if(damage >= 1)
DamageAddInfo(P,"You attack [enemy]!","[damage] damage!",'attack.wav','hit.wav')
enemy.hp -= damage
sleep(12)
if(enemy.hp <= 0)
P.Deathcheck(P,M,monstergroup)
else
if(chancehit2 == 1)
DamageAddInfo(P,"You attack [enemy]!","1 damage!",'attack.wav','hit.wav')
enemy.hp --
sleep(12)
if(enemy.hp <= 0)
P.Deathcheck(P,M,monstergroup)
else
DamageAddInfo(P,"You attack [enemy]!","No effect!",'attack.wav','dodge.wav')
sleep(12)

//DamageAddInfo Stuff
DamageAddInfo(mob/player/P,string1,string2,wav1,wav2,critstring)
for(var/obj/O in P.battlelist)
del(O)
var/color
if(round(P.hp/P.mhp*100) < 16)
color = "red"
else if(round(P.hp/P.mhp*100) < 36)
color = "green"
else
color = "white"
var/client/C = P.client
var/x = 1; var/px = 17; var/y = 15
for(var/leng = 1; leng <= length(string1); leng++)
var/obj/letter/let = new /obj/letter
let.icon = 'font.dmi'
let.icon_state = "[color][copytext(string1,leng,leng+1)]"
let.layer = MOB_LAYER + 2
let.screen_loc = "[x]:[px],[y]"
px += 17
P.battlelist += let
if(px > 32)
x++
px -= 32
C.screen += let
if(wav1)P << wav1
sleep(10)
var/reset = 0
if(critstring)
x = 1; px = 17; y = 14
for(var/leng = 1; leng <= length(critstring); leng++)
var/obj/letter/let = new /obj/letter
let.icon = 'font.dmi'
let.icon_state = "[color][copytext(critstring,leng,leng+1)]"
let.layer = MOB_LAYER + 2
let.screen_loc = "[x]:[px],[y]:9"
px += 17
P.battlelist += let
if(px > 32)
x++
px -= 32
C.screen += let
P << 'criticalhit.wav'
sleep(5)
reset = 1
if(reset == 0)
x = 1; px = 17; y = 14
for(var/leng = 1; leng <= length(string2); leng++)
var/obj/letter/let = new /obj/letter
let.icon = 'font.dmi'
let.icon_state = "[color][copytext(string2,leng,leng+1)]"
let.layer = MOB_LAYER + 2
let.screen_loc = "[x]:[px],[y]:9"
px += 17
P.battlelist += let
if(px > 32)
x++
px -= 32
C.screen += let
if(wav2)P << wav2

Problem description:
When in the Battle System that I have created, when I attack, once in a while, and completely randomly as far as I can tell, the game will temporarly freeze, extend the screen size horozontally, and post the 2nd line of text in the text panel.

Example:
Screen Text:
Line 1: "You attack the Weak Slime-A!"
Line 2: "" *FREEZE HERE, TEXT NEVER APPEARS!*

Text Panel on Right of DS:
"Miss!" *Appears AFTER freeze*

I don't understand what possibly could be wrong. I've gone over the code numerous times. It also happens when I actually do damage as well, so it isnt at the Miss only parts, so I cannot understand the problem. I know that when you add more stuff to the client.size than it can normally hold, it increases the screen size, so I understand why that happens, but theres no actual text appearing...

Sequence:
Line 1 Appears
Small Freeze
Screen Size Increases
Large Freeze
Text Appears in Text Panel
Small Freeze again
Continuation of Battle Sequence.

Thanks to anyone that can help with this problem.
Please, do not digress..

Ploaris, I suggest you replace [enemy] with [enemy.name] if you want 'the' to be gone >_>
If you want a % chance of happening, rather than doing rand() to pick certain values, you can use prob().. eg: rand(1,10); if that == 1 or 3 can be written as prob(20), which means 20% chance of happening..

You should really make a generalized procedure which takes away health, that way you don't need to keep checking if health < 0 [or program it in the deathcheck to make sure nothing happens if health<0], just a lil' advice.

And try .OGG rather than .WAV, it'll help reduce the resource size A LOT... and condensing the system with little tricks such as the compact if [eg:
if(apple)
"pie"
else
"NOO"
Can be written as
apple?"pie" : "NOO"]


Anyways:

From what I can gather, it COULD be caused from the creation of the object (such as there's too much info going on at first to go through thus it freezes) or from the sleep() statements but I'd go with the former unless someone proves me wrong (which should be easy).


- GhostAnime
I don't see anything there that may be too costly, but I did notice a few things that Ghostanime did not.

For one, I can't prove this, but sending an entire WAV file as a procedural argument may be causing it to freeze.

I think that last for() loop in damageadd could be costly as well. You're most likely drawing too fast. Add sleep() with no arguments to slow it down a little and not too noticeably.

You also might find the sound() procedure a nice find as well.
In response to GhostAnime
how would i turn my .wav files into OGG files? If the size is reduced than that might be able to prove or disprove if it is freezing due to the loading of the .wavs.

I don't even realize I'm putting the health < 0 stuff in the battle code, you are right, i should change that.

This might be surprizing, but I never knew that not putting enemy.name(or whatever) made the "the" appear, I just thought that was part of DM.

Also, the reason I use rand is because I'm just used to it. I only learned of prob about a year ago, but I've been with BYOND and making stuff for much longer, and sometimes as we know, old habits die hard.

I'll do what CaptFalcon said about making mini sleeps that arent noticeable, but will let the process work through so that it might cut down, if nothing else, the freeze time.

Thanks for all the suggestions, I really appreciate it.

NOTE: Just so everyone knows, this problem seems to have no connection to anything relating to computer Hardware. I've done it on my personal computer, as well as my school computer (Which is about 10x worse than my personal computer) and my friend's computer, which is about inbetween the other 2. The freeze time is seemingly the same (I havent timed it)...so it seems to me that its a BYOND processing problem, if it is that theres so much stuff to do.

But a few things haven't been answered. IF this is true, Why would the screen size increase? Even if it just takes a long time to go through the for loops, it shouldnt miscount text creation, especiall when miss (which takes 3 spaces on the screen), takes over 18. if I remember correctly (My code is not on my atm), the size is set to 7 or 8. (14-16 spaces). It increases by 3 spaces when this happens.

Oh well, once again, any help is appreciated. I've spent a lot of time on this entire system and I want to make sure that its in compelte working condition before the public beta of my game.
In response to Polantaris
the screen size increases when setting the screen_loc out of view.
In response to Xx Dark Wizard xX
If I remember correctly, somewhere in my original post, I said I understand why the screen is increasing size, but I don't understand why it actually is. What I mean is that, I know that when I add something to the client.view that's out of its normal view, that the screen size increases to fit this, but it shouldn't, because nothing should be being added. Nothing new gets shown on these extra spaces (Like there is when the text is too large for the screen, it shows the extra text on the enlarged parts of the screen). This shouldn't be happening, there is no reason for this. That is what I don't understand.

~Polantaris
In response to Polantaris
Polantaris wrote:
This shouldn't be happening, there is no reason for this. That is what I don't understand.

Say for example you want a full-sized map. But you'd also *really* like to have a HUD take up an entire bottom row of the screen, but you still want the full 20x20 map. What do you do? The way the viewable area for the client expands works as documented. The reference entry for screen_loc talks about how you can place something on the borders of client.screen.
In response to Jon88
Sorry for the late reply:

What it sounds like, to me, you are saying that I am increasing the viewable area on the client. But see, that's just the thing. If, what I am taking is what you mean, that shouldn't be happening. No where in my code do I accidentally increase the size of the viewable area by adding HUD stuff, and even if I was, there would be some sort of icon, or viewable object, like I normally get when I do it by accident. It seems to me that its extending the view area for no reason. The only way I've accidentally done this so far, was by adding more HUD things on the screen_loc than the X(or Y) could normally fit. But nothing gets added...unless...

Could it be possible, that when the area gets increased, the objects JUST got created, and hadn't been assigned an icon or icon state yet? That could be it! Then, by the time it finishes with the freeze, its time to delete it, so I never actually SEE the objects.

But then that leads me to wonder, where do objects get created that would cause this? Also, there is still the unanswered original question: Why does this freeze cause the text that HUD objects are supposed to be creating, come out on the Text window?
In response to CaptFalcon33035
What file type would you suggest over .wav? I don't know how to convert it, either so anything that would help that would be appreciated.
In response to Polantaris
*Bump*
In response to Polantaris
.ogg file is proably the best you can go with for high quality music files, you can google for a converter of just use Audacity. Link: http://audacity.sourceforge.net/download/windows
In response to Deathstar175
Ah alright, thanks. Does anyone have any other ideas on the cause of this entire problem (With the freezing and what not)
In response to Polantaris
Ah ha! I found something new out while doing debugs on this code.

At first I thought it only happened during Misses, but in fact, it happens only during Critcal Hits. I'll repost the code involved in this in hopes that people will help look for the problem while I do.

//crit hit code in DamageAddInfo()
if(critstring)
x = 1; px = 17; y = 14
for(var/leng = 1; leng <= length(critstring); leng++)
var/obj/letter/let = new /obj/letter
let.icon = 'font.dmi'
let.icon_state = "[color][copytext(critstring,leng,leng+1)]"
let.layer = MOB_LAYER + 2
let.screen_loc = "[x]:[px],[y]:9"
px += 17
P.battlelist += let
if(px > 32)
x++
px -= 32
C.screen += let
P << 'criticalhit.ogg'
sleep(5)
reset = 1

//crit hit info in Attack()
if(realchance == 5 || realchance == 15)
if(critical >= 1)
var/criticalchance = (M.tempagl * (rand(10,20)/10) + rand(-50,50)) - (P.tempagl * (rand(10,20)/10) + rand(-50,50))
if(criticalchance >= 1)
DamageAddInfo(P,"[M] attacks!","Critical! ","[critical] damage!",'enemyattack.ogg','hit.ogg',"Critical!")
P.hp -= critical
sleep(12)
if(P.hp <= 0)
M.Deathcheck(P,M,monstergroup)
else
DamageAddInfo(P,"[M] attacks!","Critical! ","Miss!",'enemyattack.ogg','dodge.ogg',"Critical!")
sleep(12)
else
DamageAddInfo(P,"[M] attacks!","Critical! ","Miss!",'enemyattack.ogg','dodge.ogg',"Critical!")
sleep(12)


If anyone could see what the problem is, please tell me, I'm still baffled.
In response to Polantaris
It's HTML that you're looking for, not BBCode. <dm></dm>
I'll edit this post in a second when I'm done looking it over.

Without looking it over very well, I have a few suggestions.

1.) Use prob for probability. I mean, come on, it was built for the job. Whether it's a habit to use rand or not, it's bad.

2.) Instead of creating the object, and then setting all of it's properties afterwards, why don't you just set it all up in the constructor of the object? I'm referring to let.

3.) Instead of setting the layer at runtime, why not set it at compile-time? Especially since it's constant.
In response to Aquafina
My bad I didnt realize i screwed up puttin the code in.

1) Ungh, prob means I have to change a lot of the code, and right now I'd rather keep it how it is before I change something and make everything worse.
2) I should do that.
3) Goes with 2.

That probably won't really do anything anyway, maybe make it alittle more efficient, but I'm sure the problem is something else...the letter creation works everywhere else, without any problems, except there.
In response to Polantaris
Can you please profile the world, and respond to this post with the results of the profile? It might help point out the problem.
In response to Aquafina
What do you mean "Profile the world"? As in host the world or let you be able to download and test it yourself?
In response to Polantaris
To profile: Run the game and than press CTRL+P (make sure that the game is selected and not the browser area, otherwise it'll give you a printing option rather than the profile). If dne successfully, the browser tab will load profile information. At first, there's nothing written but when you do something (eg: call a proc, verb, or even move), it'll be recorded into the profiling. To see the updated profile, do CTRL+P again or click the refresh link in the previous profile.

- GhostAnime
In response to GhostAnime
Oh and then he wants me to post that here? Alright, hold on I can get that done quick.

Edit: Heres the Profile info.
Proc Self CPU Time Total CPU Time Real Time Calls
/mob/proc/AddInfo 10.109 10.109 10.420 5
/mob/proc/CommandText 0.625 0.625 0.673 2
/mob/proc/DamageAddInfo 0.577 0.577 9.265 10
/mob/proc/Targetting 0.438 0.562 1.234 2
/mob/player/proc/saveme 0.375 0.375 0.375 1
/mob/player/proc/UpdateStat 0.094 0.094 0.094 40
/mob/proc/Attack 0.016 0.656 5.359 2
/mob/monsters/Attack 0.015 0.514 1170212642.077 8
/mob/proc/Battle 0.015 0.750 11.765 2
/mob/proc/MakeArrow 0.000 0.000 0.000 4
/mob/proc/CheckArrows 0.000 0.000 0.000 2
/mob/proc/MainBattle 0.000 23.590 1168981941.496 2
/mob/proc/CheckColorChange 0.000 0.000 0.000 8
/mob/proc/MonsterText 0.000 0.000 0.000 2
/mob/proc/InfoText 0.000 0.000 0.000 2
/mob/proc/ChooseTargetInfo 0.000 0.000 0.000 2
/mob/proc/SelectionBackground 0.000 0.000 0.000 2
/mob/monsters/Battle 0.000 10.420 1164760637.137 9
/mob/monsters/Spell 0.000 0.421 1168983792.709 5
/mob/monsters/Defend 0.000 9.906 11.313 1
/mob/player/Stat 0.000 0.094 0.094 40
/proc/AutoReboot 0.000 0.000 0.000 1
/client/Center 0.000 0.000 0.000 4
0.000 0.000 0.000 4

I believe the problem must be in AddInfo, the first one on the list. The CPU Time is alittle over 10 (seconds? sounds about what it takes, i dont time it). Lemme post that code.

AddInfo(mob/player/P,string1,string2)
for(var/obj/O in P.battlelist)
del(O)
var/color
if(round(P.hp/P.mhp*100) < 16)
color = "red"
else if(round(P.hp/P.mhp*100) < 36)
color = "green"
else
color = "white"
var/client/C = P.client
var/x = 1; var/px = 17; var/y = 15
for(var/leng = 1; leng <= length(string1); leng++)
var/obj/letter/let = new /obj/letter
let.icon_state = "[color][copytext(string1,leng,leng+1)]"
let.screen_loc = "[x]:[px],[y]"
px += 17
P.battlelist += let
if(px > 32)
x++
px -= 32
C.screen += let
sleep()
x = 1; px = 17; y = 14
for(var/leng = 1; leng <= length(string2); leng++)
var/obj/letter/let = new /obj/letter
let.icon_state = "[color][copytext(string2,leng,leng+1)]"
let.screen_loc = "[x]:[px],[y]:9"
px += 17
P.battlelist += let
if(px > 32)
x++
px -= 32
C.screen += let

I don't see why that's a problem, its the same as every other HUD Text Code, but I'll look it over later (I dont have time right now) If anyone sees a problem before I do, please say so. Thanks.

Interesting...I did it again and DamageAddInfo took even more time. This is getting to be a very confusing problem.

I'll post points of interest in the 2nd test.
Proc Self CPU Time Total CPU Time Real Time Calls
mob/proc/DamageAddInfo 11.656 11.656 29.577 18
/mob/monsters/Attack 0.015 11.344 25.764 11
In response to Polantaris
AFter talking to my friend about this, I am GLAD to say that I have figured this out!

Here is what was wrong, for anyone who cares:
Here is what I WAS Sending to DamageAddInfo:
DamageAddInfo(P,"You attack [enemy]!","Critical! ","[critical] damage!",'attack.wav','hit.wav',"Critical!")

And here is what DamageAddInfo was accepting:
DamageAddInfo(mob/player/ P,string1,string2,wav1,wav2,critstring)

Notice the stupid mistake?

P and mob/player/P: fine
"You attack [enemy]!" and string1: fine
"Critical!" and string2: fine
"[critcal] damage" (OR) "Miss!" and wav1: PROBLEM
'attack.wav' and wav2: fine
'hit.wav' and critstring: PROBLEM
"Critical!" and ?: PROBLEM

I accidentally added Critical twice. once before the damage was given, and once at the end (for critstring). I stupidly added the second Critical for no reason, causing a problem where this happened.

So if you are asking: "Why did Miss! appear on the textbox?"? Simple. when wav1 is played, it uses P << wav1.
Since wav1 was "Miss!", it sent that to the player, making it appear at the textbox! The lag is probably due to the fact of extra parameters.

I am thrilled that this problem is fixed, I've been on it for days, at least a month, probably 2.

Thanks to everyone who helped with this.

~Polantaris