ID:2272265
 
(See the best response by Nadrew.)
Code:
//tbg-mobs.dm
mob
var
HP = 1
DMG = 0

//tbg-combat.dm
mob/verb/attack(M as mob in oview(1))
usr << "You attack [M]!"
var/damage = rand(0,src.cAttack)
usr << "You dealt [damage] damage!"
M.HP -= damage


Problem description:
So I'm following along with this tutorial and I'm running into a problem with a variable being used in combat.

When I try to compile, the compiler says:
"tbg-combat.dm:5:error: M.HP: undefined var"

How can I fix this?

(Note: cAttack is a different variable from a different file, but it's not throwing an error so I'm not focusing on it.)

(Note: If you're asking why they're in separate files, another tutorial I was following organized the code for all their different parts (areas, turfs, objects, mobs, procs, etc.) into different files for organization, so I did the same. If this is the problem I can change it.)
Best response
You'd want 'mob/M as mob' and not 'M as mob' in this instance, this is called type-casting, which lets the compiler know which type the variable should be.

Keep in mind though, DM won't prevent you from passing things of the wrong type, so if you for instance, passed an object to attack() instead of a mob, you'd get a runtime error about the variable not existing instead of a compile-time error. That's where things like istype() come in handy.
Just to add to what Nadrew said, while a proc doesn't do any checking to make sure the arguments are the right type, verbs do play by slightly different rules as long as you don't call them directly like you would a proc.

What I mean is, when you have "as mob" in a verb argument, you know that argument will always be a mob--if the verb is only ever triggered by a player entering a command. You have no guarantees as to the actual type, whether it be /mob or /mob/player or /mob/NPC or whatever, but you do know it'll be a mob.

So in this case you don't need istype() to check to make sure M is really a mob, but you do need to change the definition from M to mob/M so DM knows it's supposed to be of type /mob, and therefore the . operator will work as expected.